@fluidframework/container-runtime 0.54.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.eslintrc.js +1 -1
  2. package/dist/blobManager.js +1 -1
  3. package/dist/blobManager.js.map +1 -1
  4. package/dist/containerRuntime.d.ts +17 -2
  5. package/dist/containerRuntime.d.ts.map +1 -1
  6. package/dist/containerRuntime.js +31 -21
  7. package/dist/containerRuntime.js.map +1 -1
  8. package/dist/dataStoreContext.d.ts +16 -5
  9. package/dist/dataStoreContext.d.ts.map +1 -1
  10. package/dist/dataStoreContext.js +20 -8
  11. package/dist/dataStoreContext.js.map +1 -1
  12. package/dist/dataStores.d.ts +11 -2
  13. package/dist/dataStores.d.ts.map +1 -1
  14. package/dist/dataStores.js +33 -17
  15. package/dist/dataStores.js.map +1 -1
  16. package/dist/garbageCollection.d.ts +28 -6
  17. package/dist/garbageCollection.d.ts.map +1 -1
  18. package/dist/garbageCollection.js +83 -7
  19. package/dist/garbageCollection.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.js +1 -1
  26. package/dist/packageVersion.js.map +1 -1
  27. package/dist/summaryFormat.d.ts +2 -0
  28. package/dist/summaryFormat.d.ts.map +1 -1
  29. package/dist/summaryFormat.js +0 -3
  30. package/dist/summaryFormat.js.map +1 -1
  31. package/dist/summaryManager.d.ts +1 -0
  32. package/dist/summaryManager.d.ts.map +1 -1
  33. package/dist/summaryManager.js +7 -2
  34. package/dist/summaryManager.js.map +1 -1
  35. package/lib/blobManager.js +1 -1
  36. package/lib/blobManager.js.map +1 -1
  37. package/lib/containerRuntime.d.ts +17 -2
  38. package/lib/containerRuntime.d.ts.map +1 -1
  39. package/lib/containerRuntime.js +30 -20
  40. package/lib/containerRuntime.js.map +1 -1
  41. package/lib/dataStoreContext.d.ts +16 -5
  42. package/lib/dataStoreContext.d.ts.map +1 -1
  43. package/lib/dataStoreContext.js +20 -8
  44. package/lib/dataStoreContext.js.map +1 -1
  45. package/lib/dataStores.d.ts +11 -2
  46. package/lib/dataStores.d.ts.map +1 -1
  47. package/lib/dataStores.js +33 -17
  48. package/lib/dataStores.js.map +1 -1
  49. package/lib/garbageCollection.d.ts +28 -6
  50. package/lib/garbageCollection.d.ts.map +1 -1
  51. package/lib/garbageCollection.js +83 -7
  52. package/lib/garbageCollection.js.map +1 -1
  53. package/lib/index.d.ts +1 -1
  54. package/lib/index.d.ts.map +1 -1
  55. package/lib/index.js +1 -1
  56. package/lib/index.js.map +1 -1
  57. package/lib/packageVersion.d.ts +1 -1
  58. package/lib/packageVersion.js +1 -1
  59. package/lib/packageVersion.js.map +1 -1
  60. package/lib/summaryFormat.d.ts +2 -0
  61. package/lib/summaryFormat.d.ts.map +1 -1
  62. package/lib/summaryFormat.js +0 -3
  63. package/lib/summaryFormat.js.map +1 -1
  64. package/lib/summaryManager.d.ts +1 -0
  65. package/lib/summaryManager.d.ts.map +1 -1
  66. package/lib/summaryManager.js +7 -2
  67. package/lib/summaryManager.js.map +1 -1
  68. package/package.json +21 -20
  69. package/src/blobManager.ts +1 -1
  70. package/src/containerRuntime.ts +34 -23
  71. package/src/dataStoreContext.ts +31 -9
  72. package/src/dataStores.ts +43 -20
  73. package/src/garbageCollection.ts +112 -10
  74. package/src/index.ts +1 -0
  75. package/src/packageVersion.ts +1 -1
  76. package/src/summaryFormat.ts +2 -3
  77. package/src/summaryManager.ts +9 -3
@@ -1 +1 @@
1
- {"version":3,"file":"garbageCollection.js","sourceRoot":"","sources":["../src/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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, LazyPromise, Timer } from \"@fluidframework/common-utils\";\nimport {\n cloneGCData,\n concatGarbageCollectionStates,\n concatGarbageCollectionData,\n IGCResult,\n runGarbageCollection,\n unpackChildNodesGCDetails,\n} from \"@fluidframework/garbage-collector\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n gcBlobKey,\n IGarbageCollectionData,\n IGarbageCollectionState,\n IGarbageCollectionSummaryDetails,\n ISummaryTreeWithStats,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n ReadAndParseBlob,\n RefreshSummaryResult,\n SummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils\";\nimport {\n ChildLogger,\n loggerToMonitoringContext,\n MonitoringContext,\n PerformanceEvent,\n } from \"@fluidframework/telemetry-utils\";\n\nimport { IGCRuntimeOptions } from \"./containerRuntime\";\nimport { getSummaryForDatastores } from \"./dataStores\";\nimport {\n getGCVersion,\n GCVersion,\n IContainerRuntimeMetadata,\n metadataBlobName,\n ReadFluidDataStoreAttributes,\n dataStoreAttributesBlobName,\n} from \"./summaryFormat\";\n\n/** This is the current version of garbage collection. */\nconst GCVersion = 1;\n\n// The key for the GC tree in summary.\nexport const gcTreeKey = \"gc\";\n// They prefix for GC blobs in the GC tree in summary.\nexport const gcBlobPrefix = \"__gc\";\n\n// Local storage key to turn GC on / off.\nconst runGCKey = \"Fluid.GarbageCollection.RunGC\";\n// Local storage key to turn GC test mode on / off.\nconst gcTestModeKey = \"Fluid.GarbageCollection.GCTestMode\";\n// Local storage key to turn GC sweep on / off.\nconst runSweepKey = \"Fluid.GarbageCollection.RunSweep\";\n\nconst defaultDeleteTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days\n\n/** The used state statistics of a node. */\nexport interface IUsedStateStats {\n totalNodeCount: number;\n unusedNodeCount: number;\n}\n\n/** The statistics of the system state after a garbage collection run. */\nexport interface IGCStats {\n totalNodes: number;\n deletedNodes: number;\n totalDataStores: number;\n deletedDataStores: number;\n}\n\n/** Defines the APIs for the runtime object to be passed to the garbage collector. */\nexport interface IGarbageCollectionRuntime {\n /** Returns the garbage collection data of the runtime. */\n getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;\n /** After GC has run, called to notify the runtime of routes that are used in it. */\n updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): IUsedStateStats;\n}\n\n/** Defines the contract for the garbage collector. */\nexport interface IGarbageCollector {\n /** Tells whether GC should run or not. */\n readonly shouldRunGC: boolean;\n /**\n * This tracks two things:\n * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is greater than 0, GC is enabled.\n * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.\n */\n readonly gcSummaryFeatureVersion: number;\n /** Tells whether the GC version has changed compared to the version in the latest summary. */\n readonly hasGCVersionChanged: boolean;\n /** Tells whether GC data should be written to the root of the summary tree. */\n readonly writeDataAtRoot: boolean;\n /** Run garbage collection and update the reference / used state of the system. */\n collectGarbage(\n options: { logger?: ITelemetryLogger, runGC?: boolean, runSweep?: boolean, fullGC?: boolean },\n ): Promise<IGCStats>;\n /** Summarizes the GC data and returns it as a summary tree. */\n summarize(): ISummaryTreeWithStats | undefined;\n /** Returns a map of each data store id to its GC details in the base summary. */\n getDataStoreBaseGCDetails(): Promise<Map<string, IGarbageCollectionSummaryDetails>>;\n /** Called when the latest summary of the system has been refreshed. */\n latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;\n /** Called when a node is changed. Used to detect and log when an inactive node is changed. */\n nodeChanged(id: string): void;\n /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */\n addedOutboundReference(fromNodeId: string, toNodeId: string): void;\n}\n\n/**\n * Helper class that tracks the state of an unreferenced node such as the time it was unreferenced. It also sets\n * the node's state to inactive if it remains unreferenced for a given amount of time (inactiveTimeoutMs).\n */\nclass UnreferencedStateTracker {\n private inactive: boolean = false;\n // Keeps track of all inactive events that are logged. This is used to limit the log generation for each event to 1\n // so that it is not noisy.\n private readonly inactiveEventsLogged: Set<string> = new Set();\n private readonly timer: Timer | undefined;\n\n constructor(\n public readonly unreferencedTimestampMs: number,\n inactiveTimeoutMs: number,\n ) {\n // If the timeout has already expired, the node should become inactive immediately. Otherwise, start a timer of\n // inactiveTimeoutMs after which the node will become inactive.\n if (inactiveTimeoutMs <= 0) {\n this.inactive = true;\n } else {\n this.timer = new Timer(inactiveTimeoutMs, () => { this.inactive = true; });\n this.timer.start();\n }\n }\n\n /** Stop tracking this node. Reset the unreferenced timer, if any, and reset inactive state. */\n public stopTracking() {\n this.timer?.clear();\n this.inactive = false;\n }\n\n /** Logs an error with the given properties if the node is inactive. */\n public logIfInactive(\n logger: ITelemetryLogger,\n eventName: string,\n currentTimestampMs: number,\n deleteTimeoutMs: number,\n inactiveNodeId: string,\n ) {\n if (this.inactive && !this.inactiveEventsLogged.has(eventName)) {\n logger.sendErrorEvent({\n eventName,\n age: currentTimestampMs - this.unreferencedTimestampMs,\n timeout: deleteTimeoutMs,\n id: inactiveNodeId,\n });\n this.inactiveEventsLogged.add(eventName);\n }\n }\n}\n\n/**\n * The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains\n * its state across summaries.\n */\nexport class GarbageCollector implements IGarbageCollector {\n public static create(\n provider: IGarbageCollectionRuntime,\n gcOptions: IGCRuntimeOptions,\n deleteUnusedRoutes: (unusedRoutes: string[]) => void,\n getCurrentTimestampMs: () => number,\n baseSnapshot: ISnapshotTree | undefined,\n readAndParseBlob: ReadAndParseBlob,\n baseLogger: ITelemetryLogger,\n existing: boolean,\n metadata?: IContainerRuntimeMetadata,\n ): IGarbageCollector {\n return new GarbageCollector(\n provider,\n gcOptions,\n deleteUnusedRoutes,\n getCurrentTimestampMs,\n baseSnapshot,\n readAndParseBlob,\n baseLogger,\n existing,\n metadata,\n );\n }\n\n /**\n * Tells whether GC should be run based on the GC options and local storage flags.\n */\n public readonly shouldRunGC: boolean;\n\n /**\n * This tracks two things:\n * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is greater than 0, GC is enabled.\n * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.\n */\n public get gcSummaryFeatureVersion(): number {\n return this.gcEnabled ? this.currentGCVersion : 0;\n }\n\n /**\n * Tells whether the GC version has changed compared to the version in the latest summary.\n */\n public get hasGCVersionChanged(): boolean {\n // The current version can differ from the latest summary version in two cases:\n // 1. The summary this client loaded with has data from a different GC version.\n // 2. This client's latest summary was updated from a snapshot that has a different GC version.\n return this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion;\n }\n\n /**\n * Tracks if GC is enabled for this document. This is specified during document creation and doesn't change\n * throughout its lifetime.\n */\n private readonly gcEnabled: boolean;\n private readonly shouldRunSweep: boolean;\n private readonly testMode: boolean;\n private readonly mc: MonitoringContext;\n\n /**\n * Tells whether the GC data should be written to the root of the summary tree. We do this under 2 conditions:\n * 1. If `writeDataAtRoot` GC option is enabled.\n * 2. If the base summary has the GC data written at the root. This is to support forward compatibility where when\n * we start writing the GC data at root, older versions can detect that and write at root too.\n */\n private _writeDataAtRoot: boolean = false;\n public get writeDataAtRoot(): boolean {\n return this._writeDataAtRoot;\n }\n\n // The current GC version that this container is running.\n private readonly currentGCVersion = GCVersion;\n // This is the version of GC data in the latest summary being tracked.\n private latestSummaryGCVersion: GCVersion;\n\n // Keeps track of the GC state from the last run.\n private gcDataFromLastRun: IGarbageCollectionData | undefined;\n // Keeps a list of references (edges in the GC graph) between GC runs. Each entry has a node id and a list of\n // outbound routes from that node.\n private readonly referencesSinceLastRun: Map<string, string[]> = new Map();\n\n // Promise when resolved initializes the base state of the nodes from the base summary state.\n private readonly initializeBaseStateP: Promise<void>;\n // The map of data store ids to their GC details in the base summary returned in getDataStoreGCDetails().\n private readonly dataStoreGCDetailsP: Promise<Map<string, IGarbageCollectionSummaryDetails>>;\n // The time after which an unreferenced node can be deleted. Currently, we only set the node's state to expired.\n private readonly deleteTimeoutMs: number;\n // Map of node ids to their unreferenced state tracker.\n private readonly unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();\n\n protected constructor(\n private readonly provider: IGarbageCollectionRuntime,\n private readonly gcOptions: IGCRuntimeOptions,\n /** After GC has run, called to delete objects in the runtime whose routes are unused. */\n private readonly deleteUnusedRoutes: (unusedRoutes: string[]) => void,\n /** Returns the current timestamp to be assigned to nodes that become unreferenced. */\n private readonly getCurrentTimestampMs: () => number,\n baseSnapshot: ISnapshotTree | undefined,\n readAndParseBlob: ReadAndParseBlob,\n baseLogger: ITelemetryLogger,\n existing: boolean,\n metadata?: IContainerRuntimeMetadata,\n ) {\n this.mc = loggerToMonitoringContext(\n ChildLogger.create(baseLogger, \"GarbageCollector\"));\n\n this.deleteTimeoutMs = this.gcOptions.deleteTimeoutMs ?? defaultDeleteTimeoutMs;\n\n let prevSummaryGCVersion: number | undefined;\n // GC can only be enabled during creation. After that, it can never be enabled again. So, for existing\n // documents, we get this information from the metadata blob.\n if (existing) {\n prevSummaryGCVersion = getGCVersion(metadata);\n // Existing documents which did not have metadata blob or had GC disabled have version as 0. For all\n // other exsiting documents, GC is enabled.\n this.gcEnabled = prevSummaryGCVersion > 0;\n } else {\n // For new documents, GC has to be exlicitly enabled via the gcAllowed flag in GC options.\n this.gcEnabled = gcOptions.gcAllowed === true;\n }\n // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the\n // latest tracked GC version. For new documents, we will be writing the first summary with the current version.\n this.latestSummaryGCVersion = prevSummaryGCVersion ?? this.currentGCVersion;\n\n // Whether GC should run or not. Can override with localStorage flag.\n this.shouldRunGC = this.mc.config.getBoolean(runGCKey) ?? (\n // GC must be enabled for the document.\n this.gcEnabled\n // GC must not be disabled via GC options.\n && !gcOptions.disableGC\n );\n\n // Whether GC sweep phase should run or not. If this is false, only GC mark phase is run. Can override with\n // localStorage flag.\n this.shouldRunSweep = this.shouldRunGC &&\n (this.mc.config.getBoolean(runSweepKey) ?? gcOptions.runSweep === true);\n\n // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.\n this.testMode = this.mc.config.getBoolean(gcTestModeKey) ?? gcOptions.runGCInTestMode === true;\n\n // If `writeDataAtRoot` GC option is true, we should write the GC data into the root of the summary tree. This\n // GC option is used for testing only. It will be removed once we start writing GC data into root by default.\n this._writeDataAtRoot = this.gcOptions.writeDataAtRoot === true;\n\n // Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do\n // this once since it involves fetching blobs from storage which is expensive.\n const baseSummaryStateP = new LazyPromise<IGarbageCollectionState | undefined>(async () => {\n if (baseSnapshot === undefined) {\n return undefined;\n }\n\n // For newer documents, GC data should be present in the GC tree in the root of the snapshot.\n const gcSnapshotTree = baseSnapshot.trees[gcTreeKey];\n if (gcSnapshotTree !== undefined) {\n // forward-compat - If a newer version has written the GC tree at root, we should also do the same.\n this._writeDataAtRoot = true;\n return getGCStateFromSnapshot(gcSnapshotTree, readAndParseBlob);\n }\n\n // back-compat - Older documents will have the GC blobs in each data store's summary tree. Get them and\n // consolidate into IGarbageCollectionState format.\n // Add a node for the root node that is not present in older snapshot format.\n const gcState: IGarbageCollectionState = { gcNodes: { \"/\": { outboundRoutes: [] } } };\n const dataStoreSnaphotTree = getSummaryForDatastores(baseSnapshot, metadata);\n assert(dataStoreSnaphotTree !== undefined,\n 0x2a8 /* \"Expected data store snapshot tree in base snapshot\" */);\n for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnaphotTree.trees)) {\n const blobId = dsSnapshotTree.blobs[gcBlobKey];\n if (blobId === undefined) {\n continue;\n }\n\n const gcSummaryDetails = await readAndParseBlob<IGarbageCollectionSummaryDetails>(blobId);\n // If there are no nodes for this data store, skip it.\n if (gcSummaryDetails.gcData?.gcNodes === undefined) {\n continue;\n }\n\n const dsRootId = `/${dsId}`;\n // Since we used to write GC data at data store level, we won't have an entry for the root (\"/\").\n // Construct that entry by adding root data store ids to its outbound routes.\n const initialSnapshotDetails = await readAndParseBlob<ReadFluidDataStoreAttributes>(\n dsSnapshotTree.blobs[dataStoreAttributesBlobName],\n );\n if (initialSnapshotDetails.isRootDataStore) {\n gcState.gcNodes[\"/\"].outboundRoutes.push(dsRootId);\n }\n\n for (const [id, outboundRoutes] of Object.entries(gcSummaryDetails.gcData.gcNodes)) {\n // Prefix the data store id to the GC node ids to make them relative to the root from being\n // relative to the data store. Similar to how its done in DataStore::getGCData.\n const rootId = id === \"/\" ? dsRootId : `${dsRootId}${id}`;\n gcState.gcNodes[rootId] = { outboundRoutes: Array.from(outboundRoutes) };\n }\n assert(gcState.gcNodes[dsRootId] !== undefined,\n 0x2a9 /* `GC nodes for data store ${dsId} not in GC blob` */);\n gcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;\n }\n\n // If there is only one node (root node just added above), either GC is disabled or we are loading from the\n // very first summary generated by detached container. In both cases, GC was not run - return undefined.\n return Object.keys(gcState.gcNodes).length === 1 ? undefined : gcState;\n });\n\n // Set up the initializer which initializes the base GC state from the base snapshot. Use lazy promise because\n // we only do this once - the very first time we run GC.\n this.initializeBaseStateP = new LazyPromise<void>(async () => {\n const currentTimestampMs = this.getCurrentTimestampMs();\n const baseState = await baseSummaryStateP;\n if (baseState === undefined) {\n return;\n }\n\n const gcNodes: { [ id: string ]: string[] } = {};\n for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {\n const unreferencedTimestampMs = nodeData.unreferencedTimestampMs;\n if (unreferencedTimestampMs !== undefined) {\n // Get how long it has been since the node was unreferenced. Start a timeout for the remaining time\n // left for it to be eligible for deletion.\n const unreferencedDurationMs = currentTimestampMs - unreferencedTimestampMs;\n this.unreferencedNodesState.set(\n nodeId,\n new UnreferencedStateTracker(\n unreferencedTimestampMs,\n this.deleteTimeoutMs - unreferencedDurationMs,\n ),\n );\n }\n gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n }\n this.gcDataFromLastRun = { gcNodes };\n });\n\n // Get the GC details for each data store from the GC state in the base summary. This is returned in\n // getDataStoreBaseGCDetails and is used to initialize each data store's base GC details.\n this.dataStoreGCDetailsP = new LazyPromise<Map<string, IGarbageCollectionSummaryDetails>>(async () => {\n const baseState = await baseSummaryStateP;\n if (baseState === undefined) {\n return new Map();\n }\n\n const gcNodes: { [ id: string ]: string[] } = {};\n for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {\n gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n }\n // Run GC on the nodes in the base summary to get the routes used in each node in the container.\n // This is an optimization for space (vs performance) wherein we don't need to store the used routes of\n // each node in the summary.\n const usedRoutes = runGarbageCollection(\n gcNodes,\n [ \"/\" ],\n this.mc.logger,\n ).referencedNodeIds;\n\n const dataStoreGCDetailsMap = unpackChildNodesGCDetails({ gcData: { gcNodes }, usedRoutes });\n // Currently, the data stores write the GC data. So, we need to update it's base GC details with the\n // unreferenced timestamp. Once we start writing the GC data here, we won't need to do this anymore.\n for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {\n if (nodeData.unreferencedTimestampMs !== undefined) {\n const dataStoreGCDetails = dataStoreGCDetailsMap.get(nodeId.slice(1));\n if (dataStoreGCDetails !== undefined) {\n dataStoreGCDetails.unrefTimestamp = nodeData.unreferencedTimestampMs;\n }\n }\n }\n return dataStoreGCDetailsMap;\n });\n }\n\n /**\n * Runs garbage collection and udpates the reference / used state of the nodes in the container.\n * @returns the number of data stores that have been marked as unreferenced.\n */\n public async collectGarbage(\n options: {\n /** Logger to use for logging GC events */\n logger?: ITelemetryLogger,\n /** True to run GC sweep phase after the mark phase */\n runSweep?: boolean,\n /** True to generate full GC data */\n fullGC?: boolean,\n },\n ): Promise<IGCStats> {\n const {\n logger = this.mc.logger,\n runSweep = this.shouldRunSweep,\n fullGC = this.gcOptions.runFullGC === true || this.hasGCVersionChanged,\n } = options;\n\n return PerformanceEvent.timedExecAsync(logger, { eventName: \"GarbageCollection\" }, async (event) => {\n await this.initializeBaseStateP;\n\n const gcStats: {\n deletedNodes?: number,\n totalNodes?: number,\n deletedDataStores?: number,\n totalDataStores?: number,\n } = {};\n\n // Get the runtime's GC data and run GC on the reference graph in it.\n const gcData = await this.provider.getGCData(fullGC);\n\n this.updateStateSinceLatestRun(gcData);\n\n const gcResult = runGarbageCollection(\n gcData.gcNodes,\n [ \"/\" ],\n logger,\n );\n\n const currentTimestampMs = this.getCurrentTimestampMs();\n // Update the current state of the system based on the GC run.\n this.updateCurrentState(gcData, gcResult, currentTimestampMs);\n\n const dataStoreUsedStateStats =\n this.provider.updateUsedRoutes(gcResult.referencedNodeIds, currentTimestampMs);\n\n if (runSweep) {\n // Placeholder for running sweep logic.\n }\n\n // Update stats to be reported in the peformance event.\n gcStats.deletedNodes = gcResult.deletedNodeIds.length;\n gcStats.totalNodes = gcResult.referencedNodeIds.length + gcResult.deletedNodeIds.length;\n gcStats.deletedDataStores = dataStoreUsedStateStats.unusedNodeCount;\n gcStats.totalDataStores = dataStoreUsedStateStats.totalNodeCount;\n\n // If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios\n // involving access to deleted data.\n if (this.testMode) {\n this.deleteUnusedRoutes(gcResult.deletedNodeIds);\n }\n event.end(gcStats);\n return gcStats as IGCStats;\n },\n { end: true, cancel: \"error\" });\n }\n\n /**\n * Summarizes the GC data and returns it as a summary tree.\n * We current write the entire GC state in a single blob. This can be modified later to write multiple\n * blobs. All the blob keys should start with `gcBlobPrefix`.\n */\n public summarize(): ISummaryTreeWithStats | undefined {\n if (!this.shouldRunGC || this.gcDataFromLastRun === undefined) {\n return;\n }\n\n const gcState: IGarbageCollectionState = { gcNodes: {} };\n for (const [nodeId, outboundRoutes] of Object.entries(this.gcDataFromLastRun.gcNodes)) {\n gcState.gcNodes[nodeId] = {\n outboundRoutes,\n unreferencedTimestampMs: this.unreferencedNodesState.get(nodeId)?.unreferencedTimestampMs,\n };\n }\n\n const builder = new SummaryTreeBuilder();\n builder.addBlob(`${gcBlobPrefix}_root`, JSON.stringify(gcState));\n return builder.getSummaryTree();\n }\n\n /**\n * Returns a map of data store ids to their base GC details generated from the base summary.This is used to\n * initialize the data stores with their base GC state.\n */\n public async getDataStoreBaseGCDetails(): Promise<Map<string, IGarbageCollectionSummaryDetails>> {\n return this.dataStoreGCDetailsP;\n }\n\n /**\n * Called when the latest summary of the system has been refreshed. This will be used to update the state of the\n * latest summary tracked.\n */\n public async latestSummaryStateRefreshed(\n result: RefreshSummaryResult,\n readAndParseBlob: ReadAndParseBlob,\n ): Promise<void> {\n if (!this.shouldRunGC || !result.latestSummaryUpdated) {\n return;\n }\n\n // If the summary was tracked by this client, it was the one that generated the summary in the first place.\n // Basically, it was written in the current GC version.\n if (result.wasSummaryTracked) {\n this.latestSummaryGCVersion = this.currentGCVersion;\n return;\n }\n // If the summary was not tracked by this client, update latest GC version from the snapshot in the result as\n // that is now the latest summary.\n await this.updateSummaryGCVersionFromSnapshot(result.snapshot, readAndParseBlob);\n }\n\n /**\n * Called when a node with the given id is changed. If the node is inactive, log an error.\n */\n public nodeChanged(id: string) {\n // Prefix \"/\" if needed to make it relative to the root.\n const nodeId = id.startsWith(\"/\") ? id : `/${id}`;\n this.unreferencedNodesState.get(nodeId)?.logIfInactive(\n this.mc.logger,\n \"inactiveObjectChanged\",\n this.getCurrentTimestampMs(),\n this.deleteTimeoutMs,\n nodeId,\n );\n }\n\n /**\n * Called when an outbound reference is added to a node. This is used to identify all nodes that have been\n * referenced between summaries so that their unreferenced timestamp can be reset.\n *\n * @param fromNodeId - The node from which the reference is added.\n * @param toNodeId - The node to which the reference is added.\n */\n public addedOutboundReference(fromNodeId: string, toNodeId: string) {\n const outboundRoutes = this.referencesSinceLastRun.get(fromNodeId) ?? [];\n outboundRoutes.push(toNodeId);\n this.referencesSinceLastRun.set(fromNodeId, outboundRoutes);\n }\n\n /**\n * Update the latest summary GC version from the metadata blob in the given snapshot.\n */\n private async updateSummaryGCVersionFromSnapshot(snapshot: ISnapshotTree, readAndParseBlob: ReadAndParseBlob) {\n const metadataBlobId = snapshot.blobs[metadataBlobName];\n if (metadataBlobId) {\n const metadata = await readAndParseBlob<IContainerRuntimeMetadata>(metadataBlobId);\n this.latestSummaryGCVersion = getGCVersion(metadata);\n }\n }\n\n /**\n * Updates the state of the system as per the current GC run. It does the following:\n * 1. Sets up the current GC state as per the gcData.\n * 2. Starts tracking for nodes that have become unreferenced in this run.\n * 3. Clears tracking for nodes that were unreferenced but became referenced in this run.\n * @param gcData - The data representing the reference graph on which GC is run.\n * @param gcResult - The result of the GC run on the gcData.\n * @param currentTimestampMs - The current timestamp to be used for unreferenced nodes' timestamp.\n */\n private updateCurrentState(gcData: IGarbageCollectionData, gcResult: IGCResult, currentTimestampMs: number) {\n this.gcDataFromLastRun = cloneGCData(gcData);\n this.referencesSinceLastRun.clear();\n\n // Iterate through the deleted nodes and start tracking if they became unreferenced in this run.\n for (const nodeId of gcResult.deletedNodeIds) {\n // The time when the node became unreferenced. This is added to the current GC state.\n let unreferencedTimestampMs: number = currentTimestampMs;\n const nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n if (nodeStateTracker !== undefined) {\n unreferencedTimestampMs = nodeStateTracker.unreferencedTimestampMs;\n } else {\n // Start tracking this node as it became unreferenced in this run.\n this.unreferencedNodesState.set(\n nodeId,\n new UnreferencedStateTracker(unreferencedTimestampMs, this.deleteTimeoutMs),\n );\n }\n }\n\n // Iterate through the referenced nodes and stop tracking if they were unreferenced before.\n for (const nodeId of gcResult.referencedNodeIds) {\n const nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n if (nodeStateTracker !== undefined) {\n // If this node has been unreferenced for longer than deleteTimeoutMs and is being referenced,\n // log an error as this may mean the deleteTimeoutMs is not long enough.\n nodeStateTracker.logIfInactive(\n this.mc.logger,\n \"inactiveObjectRevived\",\n currentTimestampMs,\n this.deleteTimeoutMs,\n nodeId,\n );\n // Stop tracking so as to clear out any running timers.\n nodeStateTracker.stopTracking();\n // Delete the node as we don't need to track it any more.\n this.unreferencedNodesState.delete(nodeId);\n }\n }\n }\n\n /**\n * Since GC runs periodically, the GC data that is generated only tells us the state of the world at that point in\n * time. It's possible that nodes transition from `unreferenced -> referenced -> unreferenced` between two runs. The\n * unreferenced timestamp of such nodes needs to be reset as they may have been accessed when they were referenced.\n *\n * This function identifies nodes that were referenced since last run and removes their unreferenced state, if any.\n * If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.\n */\n private updateStateSinceLatestRun(currentGCData: IGarbageCollectionData) {\n // If we haven't run GC before or no references were added since the last run, there is nothing to do.\n if (this.gcDataFromLastRun === undefined || this.referencesSinceLastRun.size === 0) {\n return;\n }\n\n /**\n * Generate a super set of the GC data that contains the nodes and edges from last run, plus any new node and\n * edges that have been added since then. To do this, combine the GC data from the last run and the current\n * run, and then add the references since last run.\n *\n * Note on why we need to combine the data from previous run, current run and all references in between -\n * 1. We need data from last run because some of its references may have been deleted since then. If those\n * references added new outbound references before getting deleted, we need to detect them.\n * 2. We need new outbound references since last run because some of them may have been deleted later. If those\n * references added new outbound references before getting deleted, we need to detect them.\n * 3. We need data from the current run because currently we may not detect when DDSs are referenced:\n * - We don't require DDSs handles to be stored in a referenced DDS. For this, we need GC at DDS level\n * which is tracked by https://github.com/microsoft/FluidFramework/issues/8470.\n * - A new data store may have \"root\" DDSs already created and we don't detect them today.\n */\n const gcDataSuperSet = concatGarbageCollectionData(this.gcDataFromLastRun, currentGCData);\n this.referencesSinceLastRun.forEach((outboundRoutes: string[], sourceNodeId: string) => {\n if (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {\n gcDataSuperSet.gcNodes[sourceNodeId] = outboundRoutes;\n } else {\n gcDataSuperSet.gcNodes[sourceNodeId].push(...outboundRoutes);\n }\n });\n\n /**\n * Run GC on the above reference graph to find all nodes that are referenced. For each one, if they are\n * unreferenced, stop tracking them and remove from unreferenced list.\n * Some of these nodes may be unreferenced now and if so, the current run will add unreferenced state for them.\n */\n const gcResult = runGarbageCollection(gcDataSuperSet.gcNodes, [\"/\"], this.mc.logger);\n for (const nodeId of gcResult.referencedNodeIds) {\n const nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n if (nodeStateTracker !== undefined) {\n // Stop tracking so as to clear out any running timers.\n nodeStateTracker.stopTracking();\n // Delete the node as we don't need to track it any more.\n this.unreferencedNodesState.delete(nodeId);\n }\n }\n }\n}\n\n/**\n * Gets the garbage collection state from the given snapshot tree. The GC state may be written into multiple blobs.\n * Merge the GC state from all such blobs and return the merged GC state.\n*/\nasync function getGCStateFromSnapshot(\n gcSnapshotTree: ISnapshotTree,\n readAndParseBlob: ReadAndParseBlob,\n): Promise<IGarbageCollectionState> {\n let rootGCState: IGarbageCollectionState = { gcNodes: {} };\n for (const key of Object.keys(gcSnapshotTree.blobs)) {\n // Skip blobs that do not stsart with the GC prefix.\n if (!key.startsWith(gcBlobPrefix)) {\n continue;\n }\n\n const blobId = gcSnapshotTree.blobs[key];\n if (blobId === undefined) {\n continue;\n }\n const gcState = await readAndParseBlob<IGarbageCollectionState>(blobId);\n assert(gcState !== undefined, 0x2ad /* \"GC blob missing from snapshot\" */);\n // Merge the GC state of this blob into the root GC state.\n rootGCState = concatGarbageCollectionStates(rootGCState, gcState);\n }\n return rootGCState;\n}\n"]}
1
+ {"version":3,"file":"garbageCollection.js","sourceRoot":"","sources":["../src/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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, LazyPromise, Timer } from \"@fluidframework/common-utils\";\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport {\n cloneGCData,\n concatGarbageCollectionStates,\n concatGarbageCollectionData,\n IGCResult,\n runGarbageCollection,\n unpackChildNodesGCDetails,\n} from \"@fluidframework/garbage-collector\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n gcBlobKey,\n IGarbageCollectionData,\n IGarbageCollectionState,\n IGarbageCollectionDetailsBase,\n ISummaryTreeWithStats,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n ReadAndParseBlob,\n RefreshSummaryResult,\n SummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils\";\nimport {\n ChildLogger,\n loggerToMonitoringContext,\n MonitoringContext,\n PerformanceEvent,\n } from \"@fluidframework/telemetry-utils\";\n\nimport { IGCRuntimeOptions } from \"./containerRuntime\";\nimport { getSummaryForDatastores } from \"./dataStores\";\nimport {\n getGCVersion,\n GCVersion,\n IContainerRuntimeMetadata,\n metadataBlobName,\n ReadFluidDataStoreAttributes,\n dataStoreAttributesBlobName,\n} from \"./summaryFormat\";\n\n/** This is the current version of garbage collection. */\nconst GCVersion = 1;\n\n// The key for the GC tree in summary.\nexport const gcTreeKey = \"gc\";\n// They prefix for GC blobs in the GC tree in summary.\nexport const gcBlobPrefix = \"__gc\";\n\n// Local storage key to turn GC on / off.\nconst runGCKey = \"Fluid.GarbageCollection.RunGC\";\n// Local storage key to turn GC test mode on / off.\nconst gcTestModeKey = \"Fluid.GarbageCollection.GCTestMode\";\n// Local storage key to turn GC sweep on / off.\nconst runSweepKey = \"Fluid.GarbageCollection.RunSweep\";\n\nconst defaultDeleteTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days\n\n/** The used state statistics of a node. */\nexport interface IUsedStateStats {\n totalNodeCount: number;\n unusedNodeCount: number;\n}\n\n/** The statistics of the system state after a garbage collection run. */\nexport interface IGCStats {\n totalNodes: number;\n deletedNodes: number;\n totalDataStores: number;\n deletedDataStores: number;\n}\n\n/** Defines the APIs for the runtime object to be passed to the garbage collector. */\nexport interface IGarbageCollectionRuntime {\n /** Before GC runs, called to notify the runtime to update any pending GC state. */\n updateStateBeforeGC(): Promise<void>;\n /** Returns the garbage collection data of the runtime. */\n getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;\n /** After GC has run, called to notify the runtime of routes that are used in it. */\n updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): IUsedStateStats;\n}\n\n/** Defines the contract for the garbage collector. */\nexport interface IGarbageCollector {\n /** Tells whether GC should run or not. */\n readonly shouldRunGC: boolean;\n /** The time in ms to expire a session for a client for gc. */\n readonly sessionExpiryTimeoutMs: number | undefined;\n /**\n * This tracks two things:\n * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is greater than 0, GC is enabled.\n * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.\n */\n readonly gcSummaryFeatureVersion: number;\n /** Tells whether the GC version has changed compared to the version in the latest summary. */\n readonly hasGCVersionChanged: boolean;\n /** Tells whether GC data should be written to the root of the summary tree. */\n readonly writeDataAtRoot: boolean;\n /** Run garbage collection and update the reference / used state of the system. */\n collectGarbage(\n options: { logger?: ITelemetryLogger, runGC?: boolean, runSweep?: boolean, fullGC?: boolean },\n ): Promise<IGCStats>;\n /** Summarizes the GC data and returns it as a summary tree. */\n summarize(): ISummaryTreeWithStats | undefined;\n /** Returns a map of each data store id to its GC details in the base summary. */\n getDataStoreBaseGCDetails(): Promise<Map<string, IGarbageCollectionDetailsBase>>;\n /** Called when the latest summary of the system has been refreshed. */\n latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;\n /** Called when a node is changed. Used to detect and log when an inactive node is changed. */\n nodeChanged(id: string): void;\n dispose(): void;\n /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */\n addedOutboundReference(fromNodeId: string, toNodeId: string): void;\n}\n\n/**\n * Helper class that tracks the state of an unreferenced node such as the time it was unreferenced. It also sets\n * the node's state to inactive if it remains unreferenced for a given amount of time (inactiveTimeoutMs).\n */\nclass UnreferencedStateTracker {\n private inactive: boolean = false;\n // Keeps track of all inactive events that are logged. This is used to limit the log generation for each event to 1\n // so that it is not noisy.\n private readonly inactiveEventsLogged: Set<string> = new Set();\n private readonly timer: Timer | undefined;\n\n constructor(\n public readonly unreferencedTimestampMs: number,\n inactiveTimeoutMs: number,\n ) {\n // If the timeout has already expired, the node should become inactive immediately. Otherwise, start a timer of\n // inactiveTimeoutMs after which the node will become inactive.\n if (inactiveTimeoutMs <= 0) {\n this.inactive = true;\n } else {\n this.timer = new Timer(inactiveTimeoutMs, () => { this.inactive = true; });\n this.timer.start();\n }\n }\n\n /** Stop tracking this node. Reset the unreferenced timer, if any, and reset inactive state. */\n public stopTracking() {\n this.timer?.clear();\n this.inactive = false;\n }\n\n /** Logs an error with the given properties if the node is inactive. */\n public logIfInactive(\n logger: ITelemetryLogger,\n eventName: string,\n currentTimestampMs: number,\n deleteTimeoutMs: number,\n inactiveNodeId: string,\n ) {\n if (this.inactive && !this.inactiveEventsLogged.has(eventName)) {\n logger.sendErrorEvent({\n eventName,\n age: currentTimestampMs - this.unreferencedTimestampMs,\n timeout: deleteTimeoutMs,\n id: inactiveNodeId,\n });\n this.inactiveEventsLogged.add(eventName);\n }\n }\n}\n\n/**\n * The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains\n * its state across summaries.\n */\nexport class GarbageCollector implements IGarbageCollector {\n public static create(\n provider: IGarbageCollectionRuntime,\n gcOptions: IGCRuntimeOptions,\n deleteUnusedRoutes: (unusedRoutes: string[]) => void,\n getCurrentTimestampMs: () => number,\n closeFn: (error?: ICriticalContainerError) => void,\n baseSnapshot: ISnapshotTree | undefined,\n readAndParseBlob: ReadAndParseBlob,\n baseLogger: ITelemetryLogger,\n existing: boolean,\n metadata?: IContainerRuntimeMetadata,\n ): IGarbageCollector {\n return new GarbageCollector(\n provider,\n gcOptions,\n deleteUnusedRoutes,\n getCurrentTimestampMs,\n closeFn,\n baseSnapshot,\n readAndParseBlob,\n baseLogger,\n existing,\n metadata,\n );\n }\n\n /**\n * Tells whether GC should be run based on the GC options and local storage flags.\n */\n public readonly shouldRunGC: boolean;\n\n /**\n * The time in ms to expire a session for a client for gc.\n */\n public readonly sessionExpiryTimeoutMs: number | undefined;\n\n /**\n * This tracks two things:\n * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is greater than 0, GC is enabled.\n * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.\n */\n public get gcSummaryFeatureVersion(): number {\n return this.gcEnabled ? this.currentGCVersion : 0;\n }\n\n /**\n * Tells whether the GC version has changed compared to the version in the latest summary.\n */\n public get hasGCVersionChanged(): boolean {\n // The current version can differ from the latest summary version in two cases:\n // 1. The summary this client loaded with has data from a different GC version.\n // 2. This client's latest summary was updated from a snapshot that has a different GC version.\n return this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion;\n }\n\n /**\n * Tracks if GC is enabled for this document. This is specified during document creation and doesn't change\n * throughout its lifetime.\n */\n private readonly gcEnabled: boolean;\n private readonly shouldRunSweep: boolean;\n private readonly testMode: boolean;\n private readonly mc: MonitoringContext;\n\n /**\n * Tells whether the GC data should be written to the root of the summary tree. We do this under 2 conditions:\n * 1. If `writeDataAtRoot` GC option is enabled.\n * 2. If the base summary has the GC data written at the root. This is to support forward compatibility where when\n * we start writing the GC data at root, older versions can detect that and write at root too.\n */\n private _writeDataAtRoot: boolean = false;\n public get writeDataAtRoot(): boolean {\n return this._writeDataAtRoot;\n }\n\n // The current GC version that this container is running.\n private readonly currentGCVersion = GCVersion;\n // This is the version of GC data in the latest summary being tracked.\n private latestSummaryGCVersion: GCVersion;\n\n // Keeps track of the GC state from the last run.\n private gcDataFromLastRun: IGarbageCollectionData | undefined;\n // Keeps a list of references (edges in the GC graph) between GC runs. Each entry has a node id and a list of\n // outbound routes from that node.\n private readonly referencesSinceLastRun: Map<string, string[]> = new Map();\n\n // Promise when resolved initializes the base state of the nodes from the base summary state.\n private readonly initializeBaseStateP: Promise<void>;\n // The map of data store ids to their GC details in the base summary returned in getDataStoreGCDetails().\n private readonly dataStoreGCDetailsP: Promise<Map<string, IGarbageCollectionDetailsBase>>;\n // The time after which an unreferenced node can be deleted. Currently, we only set the node's state to expired.\n private readonly deleteTimeoutMs: number;\n // Map of node ids to their unreferenced state tracker.\n private readonly unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();\n // The timeout responsible for closing the container when the session has expired\n private sessionExpiryTimer?: ReturnType<typeof setTimeout>;\n\n protected constructor(\n private readonly provider: IGarbageCollectionRuntime,\n private readonly gcOptions: IGCRuntimeOptions,\n /** After GC has run, called to delete objects in the runtime whose routes are unused. */\n private readonly deleteUnusedRoutes: (unusedRoutes: string[]) => void,\n /** Returns the current timestamp to be assigned to nodes that become unreferenced. */\n private readonly getCurrentTimestampMs: () => number,\n private readonly closeFn: (error?: ICriticalContainerError) => void,\n baseSnapshot: ISnapshotTree | undefined,\n readAndParseBlob: ReadAndParseBlob,\n baseLogger: ITelemetryLogger,\n existing: boolean,\n metadata?: IContainerRuntimeMetadata,\n ) {\n this.mc = loggerToMonitoringContext(\n ChildLogger.create(baseLogger, \"GarbageCollector\"));\n\n this.deleteTimeoutMs = this.gcOptions.deleteTimeoutMs ?? defaultDeleteTimeoutMs;\n\n let prevSummaryGCVersion: number | undefined;\n\n // GC can only be enabled during creation. After that, it can never be enabled again. So, for existing\n // documents, we get this information from the metadata blob. Similarly the session timeout should be\n // consistent across all clients, thus we grab it as well from the metadata blob, and set it once on creation.\n if (existing) {\n prevSummaryGCVersion = getGCVersion(metadata);\n // Existing documents which did not have metadata blob or had GC disabled have version as 0. For all\n // other exsiting documents, GC is enabled.\n this.gcEnabled = prevSummaryGCVersion > 0;\n this.sessionExpiryTimeoutMs = metadata?.sessionExpiryTimeoutMs;\n } else {\n // For new documents, GC has to be exlicitly enabled via the gcAllowed flag in GC options.\n this.gcEnabled = gcOptions.gcAllowed === true;\n this.sessionExpiryTimeoutMs = this.gcOptions.gcTestSessionTimeoutMs;\n }\n\n // If session expiry is enabled, we need to close the container when the timeout expires\n if (this.sessionExpiryTimeoutMs !== undefined) {\n // TODO: Change to ClientSessionExpiredError, issue https://github.com/microsoft/FluidFramework/issues/8605\n // this.sessionExpiryTimer = setTimeout(() => this.closeFn(\n // new ClientSessionExpiredError(`Client expired, it has lasted ${this.sessionExpiryTimeoutMs} ms.`,\n // this.sessionExpiryTimeoutMs)),\n // this.sessionExpiryTimeoutMs);\n this.sessionExpiryTimer = setTimeout(() => this.closeFn({\n errorType: \"clientSessionExpiredError\",\n message: `The client has reached the expiry time of ${this.sessionExpiryTimeoutMs} ms.`,\n }), this.sessionExpiryTimeoutMs);\n }\n\n // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the\n // latest tracked GC version. For new documents, we will be writing the first summary with the current version.\n this.latestSummaryGCVersion = prevSummaryGCVersion ?? this.currentGCVersion;\n\n // Whether GC should run or not. Can override with localStorage flag.\n this.shouldRunGC = this.mc.config.getBoolean(runGCKey) ?? (\n // GC must be enabled for the document.\n this.gcEnabled\n // GC must not be disabled via GC options.\n && !gcOptions.disableGC\n );\n\n // Whether GC sweep phase should run or not. If this is false, only GC mark phase is run. Can override with\n // localStorage flag.\n this.shouldRunSweep = this.shouldRunGC &&\n (this.mc.config.getBoolean(runSweepKey) ?? gcOptions.runSweep === true)\n && this.sessionExpiryTimer !== undefined;\n\n // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.\n this.testMode = this.mc.config.getBoolean(gcTestModeKey) ?? gcOptions.runGCInTestMode === true;\n\n // If `writeDataAtRoot` GC option is true, we should write the GC data into the root of the summary tree. This\n // GC option is used for testing only. It will be removed once we start writing GC data into root by default.\n this._writeDataAtRoot = this.gcOptions.writeDataAtRoot === true;\n\n // Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do\n // this once since it involves fetching blobs from storage which is expensive.\n const baseSummaryStateP = new LazyPromise<IGarbageCollectionState | undefined>(async () => {\n if (baseSnapshot === undefined) {\n return undefined;\n }\n\n // For newer documents, GC data should be present in the GC tree in the root of the snapshot.\n const gcSnapshotTree = baseSnapshot.trees[gcTreeKey];\n if (gcSnapshotTree !== undefined) {\n // forward-compat - If a newer version has written the GC tree at root, we should also do the same.\n this._writeDataAtRoot = true;\n return getGCStateFromSnapshot(gcSnapshotTree, readAndParseBlob);\n }\n\n // back-compat - Older documents will have the GC blobs in each data store's summary tree. Get them and\n // consolidate into IGarbageCollectionState format.\n // Add a node for the root node that is not present in older snapshot format.\n const gcState: IGarbageCollectionState = { gcNodes: { \"/\": { outboundRoutes: [] } } };\n const dataStoreSnaphotTree = getSummaryForDatastores(baseSnapshot, metadata);\n assert(dataStoreSnaphotTree !== undefined,\n 0x2a8 /* \"Expected data store snapshot tree in base snapshot\" */);\n for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnaphotTree.trees)) {\n const blobId = dsSnapshotTree.blobs[gcBlobKey];\n if (blobId === undefined) {\n continue;\n }\n\n const gcSummaryDetails = await readAndParseBlob<IGarbageCollectionDetailsBase>(blobId);\n // If there are no nodes for this data store, skip it.\n if (gcSummaryDetails.gcData?.gcNodes === undefined) {\n continue;\n }\n\n const dsRootId = `/${dsId}`;\n // Since we used to write GC data at data store level, we won't have an entry for the root (\"/\").\n // Construct that entry by adding root data store ids to its outbound routes.\n const initialSnapshotDetails = await readAndParseBlob<ReadFluidDataStoreAttributes>(\n dsSnapshotTree.blobs[dataStoreAttributesBlobName],\n );\n if (initialSnapshotDetails.isRootDataStore) {\n gcState.gcNodes[\"/\"].outboundRoutes.push(dsRootId);\n }\n\n for (const [id, outboundRoutes] of Object.entries(gcSummaryDetails.gcData.gcNodes)) {\n // Prefix the data store id to the GC node ids to make them relative to the root from being\n // relative to the data store. Similar to how its done in DataStore::getGCData.\n const rootId = id === \"/\" ? dsRootId : `${dsRootId}${id}`;\n gcState.gcNodes[rootId] = { outboundRoutes: Array.from(outboundRoutes) };\n }\n assert(gcState.gcNodes[dsRootId] !== undefined,\n 0x2a9 /* `GC nodes for data store ${dsId} not in GC blob` */);\n gcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;\n }\n\n // If there is only one node (root node just added above), either GC is disabled or we are loading from the\n // very first summary generated by detached container. In both cases, GC was not run - return undefined.\n return Object.keys(gcState.gcNodes).length === 1 ? undefined : gcState;\n });\n\n // Set up the initializer which initializes the base GC state from the base snapshot. Use lazy promise because\n // we only do this once - the very first time we run GC.\n this.initializeBaseStateP = new LazyPromise<void>(async () => {\n const currentTimestampMs = this.getCurrentTimestampMs();\n const baseState = await baseSummaryStateP;\n if (baseState === undefined) {\n return;\n }\n\n const gcNodes: { [ id: string ]: string[] } = {};\n for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {\n const unreferencedTimestampMs = nodeData.unreferencedTimestampMs;\n if (unreferencedTimestampMs !== undefined) {\n // Get how long it has been since the node was unreferenced. Start a timeout for the remaining time\n // left for it to be eligible for deletion.\n const unreferencedDurationMs = currentTimestampMs - unreferencedTimestampMs;\n this.unreferencedNodesState.set(\n nodeId,\n new UnreferencedStateTracker(\n unreferencedTimestampMs,\n this.deleteTimeoutMs - unreferencedDurationMs,\n ),\n );\n }\n gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n }\n this.gcDataFromLastRun = { gcNodes };\n });\n\n // Get the GC details for each data store from the GC state in the base summary. This is returned in\n // getDataStoreBaseGCDetails and is used to initialize each data store's GC state.\n this.dataStoreGCDetailsP = new LazyPromise<Map<string, IGarbageCollectionDetailsBase>>(async () => {\n const baseState = await baseSummaryStateP;\n if (baseState === undefined) {\n return new Map();\n }\n\n const gcNodes: { [ id: string ]: string[] } = {};\n for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {\n gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n }\n // Run GC on the nodes in the base summary to get the routes used in each node in the container.\n // This is an optimization for space (vs performance) wherein we don't need to store the used routes of\n // each node in the summary.\n const usedRoutes = runGarbageCollection(\n gcNodes,\n [ \"/\" ],\n this.mc.logger,\n ).referencedNodeIds;\n\n const dataStoreGCDetailsMap = unpackChildNodesGCDetails({ gcData: { gcNodes }, usedRoutes });\n // Currently, the data stores write the GC data. So, we need to update it's base GC details with the\n // unreferenced timestamp. Once we start writing the GC data here, we won't need to do this anymore.\n for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {\n if (nodeData.unreferencedTimestampMs !== undefined) {\n const dataStoreGCDetails = dataStoreGCDetailsMap.get(nodeId.slice(1));\n if (dataStoreGCDetails !== undefined) {\n dataStoreGCDetails.unrefTimestamp = nodeData.unreferencedTimestampMs;\n }\n }\n }\n return dataStoreGCDetailsMap;\n });\n }\n\n /**\n * Runs garbage collection and udpates the reference / used state of the nodes in the container.\n * @returns the number of data stores that have been marked as unreferenced.\n */\n public async collectGarbage(\n options: {\n /** Logger to use for logging GC events */\n logger?: ITelemetryLogger,\n /** True to run GC sweep phase after the mark phase */\n runSweep?: boolean,\n /** True to generate full GC data */\n fullGC?: boolean,\n },\n ): Promise<IGCStats> {\n const {\n logger = this.mc.logger,\n runSweep = this.shouldRunSweep,\n fullGC = this.gcOptions.runFullGC === true || this.hasGCVersionChanged,\n } = options;\n\n return PerformanceEvent.timedExecAsync(logger, { eventName: \"GarbageCollection\" }, async (event) => {\n await this.initializeBaseStateP;\n\n // Let the runtime update its pending state before GC runs.\n await this.provider.updateStateBeforeGC();\n\n const gcStats: {\n deletedNodes?: number,\n totalNodes?: number,\n deletedDataStores?: number,\n totalDataStores?: number,\n } = {};\n\n // Get the runtime's GC data and run GC on the reference graph in it.\n const gcData = await this.provider.getGCData(fullGC);\n\n this.updateStateSinceLatestRun(gcData);\n\n const gcResult = runGarbageCollection(\n gcData.gcNodes,\n [ \"/\" ],\n logger,\n );\n\n const currentTimestampMs = this.getCurrentTimestampMs();\n // Update the current state of the system based on the GC run.\n this.updateCurrentState(gcData, gcResult, currentTimestampMs);\n\n const dataStoreUsedStateStats =\n this.provider.updateUsedRoutes(gcResult.referencedNodeIds, currentTimestampMs);\n\n if (runSweep) {\n // Placeholder for running sweep logic.\n }\n\n // Update stats to be reported in the peformance event.\n gcStats.deletedNodes = gcResult.deletedNodeIds.length;\n gcStats.totalNodes = gcResult.referencedNodeIds.length + gcResult.deletedNodeIds.length;\n gcStats.deletedDataStores = dataStoreUsedStateStats.unusedNodeCount;\n gcStats.totalDataStores = dataStoreUsedStateStats.totalNodeCount;\n\n // If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios\n // involving access to deleted data.\n if (this.testMode) {\n this.deleteUnusedRoutes(gcResult.deletedNodeIds);\n }\n event.end(gcStats);\n return gcStats as IGCStats;\n },\n { end: true, cancel: \"error\" });\n }\n\n /**\n * Summarizes the GC data and returns it as a summary tree.\n * We current write the entire GC state in a single blob. This can be modified later to write multiple\n * blobs. All the blob keys should start with `gcBlobPrefix`.\n */\n public summarize(): ISummaryTreeWithStats | undefined {\n if (!this.shouldRunGC || this.gcDataFromLastRun === undefined) {\n return;\n }\n\n const gcState: IGarbageCollectionState = { gcNodes: {} };\n for (const [nodeId, outboundRoutes] of Object.entries(this.gcDataFromLastRun.gcNodes)) {\n gcState.gcNodes[nodeId] = {\n outboundRoutes,\n unreferencedTimestampMs: this.unreferencedNodesState.get(nodeId)?.unreferencedTimestampMs,\n };\n }\n\n const builder = new SummaryTreeBuilder();\n builder.addBlob(`${gcBlobPrefix}_root`, JSON.stringify(gcState));\n return builder.getSummaryTree();\n }\n\n /**\n * Returns a map of data store ids to their base GC details generated from the base summary.This is used to\n * initialize the GC state of data stores.\n */\n public async getDataStoreBaseGCDetails(): Promise<Map<string, IGarbageCollectionDetailsBase>> {\n return this.dataStoreGCDetailsP;\n }\n\n /**\n * Called when the latest summary of the system has been refreshed. This will be used to update the state of the\n * latest summary tracked.\n */\n public async latestSummaryStateRefreshed(\n result: RefreshSummaryResult,\n readAndParseBlob: ReadAndParseBlob,\n ): Promise<void> {\n if (!this.shouldRunGC || !result.latestSummaryUpdated) {\n return;\n }\n\n // If the summary was tracked by this client, it was the one that generated the summary in the first place.\n // Basically, it was written in the current GC version.\n if (result.wasSummaryTracked) {\n this.latestSummaryGCVersion = this.currentGCVersion;\n return;\n }\n // If the summary was not tracked by this client, update latest GC version from the snapshot in the result as\n // that is now the latest summary.\n await this.updateSummaryGCVersionFromSnapshot(result.snapshot, readAndParseBlob);\n }\n\n /**\n * Called when a node with the given id is changed. If the node is inactive, log an error.\n */\n public nodeChanged(id: string) {\n // Prefix \"/\" if needed to make it relative to the root.\n const nodeId = id.startsWith(\"/\") ? id : `/${id}`;\n this.unreferencedNodesState.get(nodeId)?.logIfInactive(\n this.mc.logger,\n \"inactiveObjectChanged\",\n this.getCurrentTimestampMs(),\n this.deleteTimeoutMs,\n nodeId,\n );\n }\n\n public dispose(): void {\n if (this.sessionExpiryTimer !== undefined) {\n clearTimeout(this.sessionExpiryTimer);\n this.sessionExpiryTimer = undefined;\n }\n }\n\n /**\n * Called when an outbound reference is added to a node. This is used to identify all nodes that have been\n * referenced between summaries so that their unreferenced timestamp can be reset.\n *\n * @param fromNodeId - The node from which the reference is added.\n * @param toNodeId - The node to which the reference is added.\n */\n public addedOutboundReference(fromNodeId: string, toNodeId: string) {\n const outboundRoutes = this.referencesSinceLastRun.get(fromNodeId) ?? [];\n outboundRoutes.push(toNodeId);\n this.referencesSinceLastRun.set(fromNodeId, outboundRoutes);\n }\n\n /**\n * Update the latest summary GC version from the metadata blob in the given snapshot.\n */\n private async updateSummaryGCVersionFromSnapshot(snapshot: ISnapshotTree, readAndParseBlob: ReadAndParseBlob) {\n const metadataBlobId = snapshot.blobs[metadataBlobName];\n if (metadataBlobId) {\n const metadata = await readAndParseBlob<IContainerRuntimeMetadata>(metadataBlobId);\n this.latestSummaryGCVersion = getGCVersion(metadata);\n }\n }\n\n /**\n * Updates the state of the system as per the current GC run. It does the following:\n * 1. Sets up the current GC state as per the gcData.\n * 2. Starts tracking for nodes that have become unreferenced in this run.\n * 3. Clears tracking for nodes that were unreferenced but became referenced in this run.\n * @param gcData - The data representing the reference graph on which GC is run.\n * @param gcResult - The result of the GC run on the gcData.\n * @param currentTimestampMs - The current timestamp to be used for unreferenced nodes' timestamp.\n */\n private updateCurrentState(gcData: IGarbageCollectionData, gcResult: IGCResult, currentTimestampMs: number) {\n this.gcDataFromLastRun = cloneGCData(gcData);\n this.referencesSinceLastRun.clear();\n\n // Iterate through the deleted nodes and start tracking if they became unreferenced in this run.\n for (const nodeId of gcResult.deletedNodeIds) {\n // The time when the node became unreferenced. This is added to the current GC state.\n let unreferencedTimestampMs: number = currentTimestampMs;\n const nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n if (nodeStateTracker !== undefined) {\n unreferencedTimestampMs = nodeStateTracker.unreferencedTimestampMs;\n } else {\n // Start tracking this node as it became unreferenced in this run.\n this.unreferencedNodesState.set(\n nodeId,\n new UnreferencedStateTracker(unreferencedTimestampMs, this.deleteTimeoutMs),\n );\n }\n }\n\n // Iterate through the referenced nodes and stop tracking if they were unreferenced before.\n for (const nodeId of gcResult.referencedNodeIds) {\n const nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n if (nodeStateTracker !== undefined) {\n // If this node has been unreferenced for longer than deleteTimeoutMs and is being referenced,\n // log an error as this may mean the deleteTimeoutMs is not long enough.\n nodeStateTracker.logIfInactive(\n this.mc.logger,\n \"inactiveObjectRevived\",\n currentTimestampMs,\n this.deleteTimeoutMs,\n nodeId,\n );\n // Stop tracking so as to clear out any running timers.\n nodeStateTracker.stopTracking();\n // Delete the node as we don't need to track it any more.\n this.unreferencedNodesState.delete(nodeId);\n }\n }\n }\n\n /**\n * Since GC runs periodically, the GC data that is generated only tells us the state of the world at that point in\n * time. It's possible that nodes transition from `unreferenced -> referenced -> unreferenced` between two runs. The\n * unreferenced timestamp of such nodes needs to be reset as they may have been accessed when they were referenced.\n *\n * This function identifies nodes that were referenced since last run and removes their unreferenced state, if any.\n * If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.\n */\n private updateStateSinceLatestRun(currentGCData: IGarbageCollectionData) {\n // If we haven't run GC before or no references were added since the last run, there is nothing to do.\n if (this.gcDataFromLastRun === undefined || this.referencesSinceLastRun.size === 0) {\n return;\n }\n\n // Validate that we have identified all references correctly.\n this.validateReferenceCorrectness(currentGCData);\n\n /**\n * Generate a super set of the GC data that contains the nodes and edges from last run, plus any new node and\n * edges that have been added since then. To do this, combine the GC data from the last run and the current\n * run, and then add the references since last run.\n *\n * Note on why we need to combine the data from previous run, current run and all references in between -\n * 1. We need data from last run because some of its references may have been deleted since then. If those\n * references added new outbound references before getting deleted, we need to detect them.\n * 2. We need new outbound references since last run because some of them may have been deleted later. If those\n * references added new outbound references before getting deleted, we need to detect them.\n * 3. We need data from the current run because currently we may not detect when DDSs are referenced:\n * - We don't require DDSs handles to be stored in a referenced DDS. For this, we need GC at DDS level\n * which is tracked by https://github.com/microsoft/FluidFramework/issues/8470.\n * - A new data store may have \"root\" DDSs already created and we don't detect them today.\n */\n const gcDataSuperSet = concatGarbageCollectionData(this.gcDataFromLastRun, currentGCData);\n this.referencesSinceLastRun.forEach((outboundRoutes: string[], sourceNodeId: string) => {\n if (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {\n gcDataSuperSet.gcNodes[sourceNodeId] = outboundRoutes;\n } else {\n gcDataSuperSet.gcNodes[sourceNodeId].push(...outboundRoutes);\n }\n });\n\n /**\n * Run GC on the above reference graph to find all nodes that are referenced. For each one, if they are\n * unreferenced, stop tracking them and remove from unreferenced list.\n * Some of these nodes may be unreferenced now and if so, the current run will add unreferenced state for them.\n */\n const gcResult = runGarbageCollection(gcDataSuperSet.gcNodes, [\"/\"], this.mc.logger);\n for (const nodeId of gcResult.referencedNodeIds) {\n const nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n if (nodeStateTracker !== undefined) {\n // Stop tracking so as to clear out any running timers.\n nodeStateTracker.stopTracking();\n // Delete the node as we don't need to track it any more.\n this.unreferencedNodesState.delete(nodeId);\n }\n }\n }\n\n /**\n * Validates that all new references are correctly identified and processed. The basic principle for validation is\n * that we should not have new references in the reference graph (GC data) that have not been notified to the\n * garbage collector via `referenceAdded`.\n * We validate that the references in the current reference graph should be a subset of the references in the last\n * run's reference graph + references since the last run.\n * @param currentGCData - The GC data (reference graph) from the current GC run.\n */\n private validateReferenceCorrectness(currentGCData: IGarbageCollectionData) {\n assert(this.gcDataFromLastRun !== undefined, 0x2b7\n /* \"Can't validate correctness without GC data from last run\" */);\n\n // Get a list of all the outbound routes (or references) in the current GC data.\n const currentReferences: string[] = [];\n for (const [nodeId, outboundRoutes] of Object.entries(currentGCData.gcNodes)) {\n /**\n * Remove routes from a child node to its parent which is added implicitly by the runtime. For instance,\n * each adds its data store as an outbound route to mark it as referenced if the DDS is referenced.\n * We won't get any explicit notification for these references so they must be removed before validation.\n */\n const explicitRoutes = outboundRoutes.filter((route) => !nodeId.startsWith(route));\n currentReferences.push(...explicitRoutes);\n }\n\n // Get a list of outbound routes (or references) from the last run's GC data plus references added since the\n // last run that were notified via `referenceAdded`.\n const explicitReferences: string[] = [];\n for (const [, outboundRoutes] of Object.entries(this.gcDataFromLastRun.gcNodes)) {\n explicitReferences.push(...outboundRoutes);\n }\n this.referencesSinceLastRun.forEach((outboundRoutes: string[]) => {\n explicitReferences.push(...outboundRoutes);\n });\n\n // Validate that the current reference graph doesn't have references that we are not already aware of. If this\n // happens, it might indicate data corruption since we may delete objects prematurely.\n currentReferences.forEach((route: string) => {\n // Validate references for data stores only whose routes are of the format \"/dataStoreId\". Currently, layers\n // below data stores don't have GC implemented so there is no guarantee their references will be notified.\n if (route.split(\"/\").length === 2 && !explicitReferences.includes(route)) {\n // We should ideally throw a data corruption error here. However, send an error for now until we have\n // implemented sweep and have reasonable confidence in the sweep process.\n\n // To be enabled when this issue is fixed - https://github.com/microsoft/FluidFramework/issues/8672\n /**\n this.mc.logger.sendErrorEvent({\n eventName: \"gcUnknownOutboundRoute\",\n route,\n });\n */\n }\n });\n }\n}\n\n/**\n * Gets the garbage collection state from the given snapshot tree. The GC state may be written into multiple blobs.\n * Merge the GC state from all such blobs and return the merged GC state.\n*/\nasync function getGCStateFromSnapshot(\n gcSnapshotTree: ISnapshotTree,\n readAndParseBlob: ReadAndParseBlob,\n): Promise<IGarbageCollectionState> {\n let rootGCState: IGarbageCollectionState = { gcNodes: {} };\n for (const key of Object.keys(gcSnapshotTree.blobs)) {\n // Skip blobs that do not stsart with the GC prefix.\n if (!key.startsWith(gcBlobPrefix)) {\n continue;\n }\n\n const blobId = gcSnapshotTree.blobs[key];\n if (blobId === undefined) {\n continue;\n }\n const gcState = await readAndParseBlob<IGarbageCollectionState>(blobId);\n assert(gcState !== undefined, 0x2ad /* \"GC blob missing from snapshot\" */);\n // Merge the GC state of this blob into the root GC state.\n rootGCState = concatGarbageCollectionStates(rootGCState, gcState);\n }\n return rootGCState;\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { ContainerMessageType, IChunkedOp, ContainerRuntimeMessage, IGCRuntimeOptions, ISummaryRuntimeOptions, IContainerRuntimeOptions, isRuntimeMessage, unpackRuntimeMessage, ScheduleManager, agentSchedulerId, ContainerRuntime, } from "./containerRuntime";
5
+ export { ContainerMessageType, IChunkedOp, ContainerRuntimeMessage, IGCRuntimeOptions, ISummaryRuntimeOptions, IContainerRuntimeOptions, isRuntimeMessage, RuntimeMessage, unpackRuntimeMessage, ScheduleManager, agentSchedulerId, ContainerRuntime, } from "./containerRuntime";
6
6
  export * from "./deltaScheduler";
7
7
  export * from "./dataStoreRegistry";
8
8
  export { gcBlobPrefix, gcTreeKey, IGarbageCollectionRuntime, IGCStats, IUsedStateStats, } from "./garbageCollection";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,oBAAoB,EACpB,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACH,YAAY,EACZ,SAAS,EACT,yBAAyB,EACzB,QAAQ,EACR,eAAe,GAClB,MAAM,qBAAqB,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,oBAAoB,EACpB,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACH,YAAY,EACZ,SAAS,EACT,yBAAyB,EACzB,QAAQ,EACR,eAAe,GAClB,MAAM,qBAAqB,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC"}
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { ContainerMessageType, isRuntimeMessage, unpackRuntimeMessage, ScheduleManager, agentSchedulerId, ContainerRuntime, } from "./containerRuntime";
5
+ export { ContainerMessageType, isRuntimeMessage, RuntimeMessage, unpackRuntimeMessage, ScheduleManager, agentSchedulerId, ContainerRuntime, } from "./containerRuntime";
6
6
  export * from "./deltaScheduler";
7
7
  export * from "./dataStoreRegistry";
8
8
  export { gcBlobPrefix, gcTreeKey, } from "./garbageCollection";
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,oBAAoB,EAMpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACH,YAAY,EACZ,SAAS,GAIZ,MAAM,qBAAqB,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAoC,0BAA0B,EAAE,MAAM,gCAAgC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n ContainerMessageType,\n IChunkedOp,\n ContainerRuntimeMessage,\n IGCRuntimeOptions,\n ISummaryRuntimeOptions,\n IContainerRuntimeOptions,\n isRuntimeMessage,\n unpackRuntimeMessage,\n ScheduleManager,\n agentSchedulerId,\n ContainerRuntime,\n} from \"./containerRuntime\";\nexport * from \"./deltaScheduler\";\nexport * from \"./dataStoreRegistry\";\nexport {\n gcBlobPrefix,\n gcTreeKey,\n IGarbageCollectionRuntime,\n IGCStats,\n IUsedStateStats,\n} from \"./garbageCollection\";\nexport * from \"./pendingStateManager\";\nexport * from \"./summarizer\";\nexport * from \"./summarizerTypes\";\nexport * from \"./summaryCollection\";\nexport { ICancellableSummarizerController, neverCancelledSummaryToken } from \"./runWhileConnectedCoordinator\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,oBAAoB,EAMpB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACH,YAAY,EACZ,SAAS,GAIZ,MAAM,qBAAqB,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAoC,0BAA0B,EAAE,MAAM,gCAAgC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n ContainerMessageType,\n IChunkedOp,\n ContainerRuntimeMessage,\n IGCRuntimeOptions,\n ISummaryRuntimeOptions,\n IContainerRuntimeOptions,\n isRuntimeMessage,\n RuntimeMessage,\n unpackRuntimeMessage,\n ScheduleManager,\n agentSchedulerId,\n ContainerRuntime,\n} from \"./containerRuntime\";\nexport * from \"./deltaScheduler\";\nexport * from \"./dataStoreRegistry\";\nexport {\n gcBlobPrefix,\n gcTreeKey,\n IGarbageCollectionRuntime,\n IGCStats,\n IUsedStateStats,\n} from \"./garbageCollection\";\nexport * from \"./pendingStateManager\";\nexport * from \"./summarizer\";\nexport * from \"./summarizerTypes\";\nexport * from \"./summaryCollection\";\nexport { ICancellableSummarizerController, neverCancelledSummaryToken } from \"./runWhileConnectedCoordinator\";\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/container-runtime";
8
- export declare const pkgVersion = "0.54.0";
8
+ export declare const pkgVersion = "0.55.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/container-runtime";
8
- export const pkgVersion = "0.54.0";
8
+ export const pkgVersion = "0.55.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"0.54.0\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"0.55.0\";\n"]}
@@ -53,6 +53,8 @@ export interface IContainerRuntimeMetadata extends ICreateContainerMetadata {
53
53
  readonly gcFeature?: GCVersion;
54
54
  /** Counter of the last summary happened, increments every time we summarize */
55
55
  readonly summaryCount?: number;
56
+ /** If this is present, the session for this container will expire after this time and the container will close */
57
+ readonly sessionExpiryTimeoutMs?: number;
56
58
  }
57
59
  export interface ICreateContainerMetadata {
58
60
  /** Runtime version of the container when it was first created */
@@ -1 +1 @@
1
- {"version":3,"file":"summaryFormat.d.ts","sourceRoot":"","sources":["../src/summaryFormat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"summaryFormat.d.ts","sourceRoot":"","sources":["../src/summaryFormat.ts"],"names":[],"mappings":"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"}
@@ -27,7 +27,6 @@ export function getAttributesFormatVersion(attributes) {
27
27
  */
28
28
  return 0;
29
29
  }
30
- // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
31
30
  export function hasIsolatedChannels(attributes) {
32
31
  return !!attributes.summaryFormatVersion && !attributes.disableIsolatedChannels;
33
32
  }
@@ -44,7 +43,6 @@ export const extractSummaryMetadataMessage = (message) => message === undefined
44
43
  timestamp: message.timestamp,
45
44
  type: message.type,
46
45
  };
47
- // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
48
46
  export function getMetadataFormatVersion(metadata) {
49
47
  var _a;
50
48
  /**
@@ -64,7 +62,6 @@ export const metadataBlobName = ".metadata";
64
62
  export const chunksBlobName = ".chunks";
65
63
  export const electedSummarizerBlobName = ".electedSummarizer";
66
64
  export const blobsTreeName = ".blobs";
67
- // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
68
65
  export function rootHasIsolatedChannels(metadata) {
69
66
  return !!metadata && !metadata.disableIsolatedChannels;
70
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"summaryFormat.js","sourceRoot":"","sources":["../src/summaryFormat.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 { assert } from \"@fluidframework/common-utils\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { channelsTreeName, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\n\ntype OmitAttributesVersions<T> = Omit<T, \"snapshotFormatVersion\" | \"summaryFormatVersion\">;\ninterface IFluidDataStoreAttributes0 {\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion?: undefined;\n pkg: string;\n /**\n * This tells whether a data store is root. Root data stores are never collected.\n * Non-root data stores may be collected if they are not used. If this is not present, default it to\n * true. This will ensure that older data stores are incorrectly collected.\n */\n readonly isRootDataStore?: boolean;\n}\ninterface IFluidDataStoreAttributes1 extends OmitAttributesVersions<IFluidDataStoreAttributes0> {\n readonly snapshotFormatVersion: \"0.1\";\n readonly summaryFormatVersion?: undefined;\n}\ninterface IFluidDataStoreAttributes2 extends OmitAttributesVersions<IFluidDataStoreAttributes1> {\n /** Switch from snapshotFormatVersion to summaryFormatVersion */\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion: 2;\n /**\n * True if channels are not isolated in .channels subtrees, otherwise isolated.\n * This is required in both datastore attributes as well as the root container,\n * because reused summary handles may cause different format versions in each\n * datastore subtree within the summary.\n */\n readonly disableIsolatedChannels?: true;\n}\n/**\n * Added IFluidDataStoreAttributes similar to IChannelAttributes which will tell the attributes of a\n * store like the package, snapshotFormatVersion to take different decisions based on a particular\n * snapshotFormatVersion.\n */\nexport type ReadFluidDataStoreAttributes =\n | IFluidDataStoreAttributes0\n | IFluidDataStoreAttributes1\n | IFluidDataStoreAttributes2;\nexport type WriteFluidDataStoreAttributes = IFluidDataStoreAttributes1 | IFluidDataStoreAttributes2;\n\nexport function getAttributesFormatVersion(attributes: ReadFluidDataStoreAttributes): number {\n if (attributes.summaryFormatVersion) {\n /**\n * Version 2+: Introduces .channels trees for isolation of\n * channel trees from data store objects.\n */\n return attributes.summaryFormatVersion;\n } else if (attributes.snapshotFormatVersion === \"0.1\") {\n /**\n * Version 1: from this version the pkg within the data store\n * attributes blob is a JSON array rather than a string.\n */\n return 1;\n }\n /**\n * Version 0: format version is missing from summary.\n * This indicates it is an older version.\n */\n return 0;\n}\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function hasIsolatedChannels(attributes: ReadFluidDataStoreAttributes): boolean {\n return !!attributes.summaryFormatVersion && !attributes.disableIsolatedChannels;\n}\n\nexport type GCVersion = number;\nexport interface IContainerRuntimeMetadata extends ICreateContainerMetadata {\n readonly summaryFormatVersion: 1;\n /** The last message processed at the time of summary. Only primitive propertiy types are added to the summary. */\n readonly message: ISummaryMetadataMessage | undefined;\n /** True if channels are not isolated in .channels subtrees, otherwise isolated. */\n readonly disableIsolatedChannels?: true;\n /** 0 to disable GC, > 0 to enable GC, undefined defaults to disabled. */\n readonly gcFeature?: GCVersion;\n /** Counter of the last summary happened, increments every time we summarize */\n readonly summaryCount?: number;\n}\n\nexport interface ICreateContainerMetadata {\n /** Runtime version of the container when it was first created */\n createContainerRuntimeVersion?: string;\n /** Timestamp of the container when it was first created */\n createContainerTimestamp?: number;\n}\n\n/** The properties of an ISequencedDocumentMessage to be stored in the metadata blob in summary. */\nexport type ISummaryMetadataMessage = Pick<ISequencedDocumentMessage,\n | \"clientId\"\n | \"clientSequenceNumber\"\n | \"minimumSequenceNumber\"\n | \"referenceSequenceNumber\"\n | \"sequenceNumber\"\n | \"timestamp\"\n | \"type\">;\n\n/**\n * Extracts the properties from an ISequencedDocumentMessage as defined by ISummaryMetadataMessage. This message is\n * added to the metadata blob in summary.\n */\nexport const extractSummaryMetadataMessage = (\n message?: ISequencedDocumentMessage,\n): ISummaryMetadataMessage | undefined => message === undefined ? undefined : {\n clientId: message.clientId,\n clientSequenceNumber: message.clientSequenceNumber,\n minimumSequenceNumber: message.minimumSequenceNumber,\n referenceSequenceNumber: message.referenceSequenceNumber,\n sequenceNumber: message.sequenceNumber,\n timestamp: message.timestamp,\n type: message.type,\n};\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function getMetadataFormatVersion(metadata?: IContainerRuntimeMetadata): number {\n /**\n * Version 2+: Introduces runtime sequence number for data verification.\n *\n * Version 1+: Introduces .metadata blob and .channels trees for isolation of\n * data store trees from container-level objects.\n * Also introduces enableGC option stored in the summary.\n *\n * Version 0: metadata blob missing; format version is missing from summary.\n * This indicates it is an older version.\n */\n return metadata?.summaryFormatVersion ?? 0;\n}\n\nexport const aliasBlobName = \".aliases\";\nexport const metadataBlobName = \".metadata\";\nexport const chunksBlobName = \".chunks\";\nexport const electedSummarizerBlobName = \".electedSummarizer\";\nexport const blobsTreeName = \".blobs\";\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function rootHasIsolatedChannels(metadata?: IContainerRuntimeMetadata): boolean {\n return !!metadata && !metadata.disableIsolatedChannels;\n}\n\nexport function getGCVersion(metadata?: IContainerRuntimeMetadata): GCVersion {\n if (!metadata) {\n // Force to 0/disallowed in prior versions\n return 0;\n }\n return metadata.gcFeature ?? 0;\n}\n\nexport const protocolTreeName = \".protocol\";\n\n/**\n * List of tree IDs at the container level which are reserved.\n * This is for older versions of summaries that do not yet have an\n * isolated data stores namespace. Without the namespace, this must\n * be used to prevent name collisions with data store IDs.\n */\nexport const nonDataStorePaths = [protocolTreeName, \".logTail\", \".serviceProtocol\", blobsTreeName];\n\nexport const dataStoreAttributesBlobName = \".component\";\n\n/**\n * Modifies summary tree and stats to put tree under .channels tree.\n * Converts from: {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} },\n * }\n * to: {\n * type: SummaryType.Tree,\n * tree: {\n * \".channels\": {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} }\n * },\n * },\n * }\n * And adds +1 to treeNodeCount in stats.\n * @param summarizeResult - summary tree and stats to modify\n */\nexport function wrapSummaryInChannelsTree(summarizeResult: ISummaryTreeWithStats): void {\n summarizeResult.summary = {\n type: SummaryType.Tree,\n tree: { [channelsTreeName]: summarizeResult.summary },\n };\n summarizeResult.stats.treeNodeCount++;\n}\n\nexport async function getFluidDataStoreAttributes(\n storage: IDocumentStorageService,\n snapshot: ISnapshotTree,\n): Promise<ReadFluidDataStoreAttributes> {\n const attributes = await readAndParse<ReadFluidDataStoreAttributes>(\n storage, snapshot.blobs[dataStoreAttributesBlobName]);\n // Use the snapshotFormatVersion to determine how the pkg is encoded in the snapshot.\n // For snapshotFormatVersion = \"0.1\" (1) or above, pkg is jsonified, otherwise it is just a string.\n // However the feature of loading a detached container from snapshot, is added when the\n // snapshotFormatVersion is at least \"0.1\" (1), so we don't expect it to be anything else.\n const formatVersion = getAttributesFormatVersion(attributes);\n assert(formatVersion > 0,\n 0x1d5 /* `Invalid snapshot format version ${attributes.snapshotFormatVersion}` */);\n return attributes;\n}\n"]}
1
+ {"version":3,"file":"summaryFormat.js","sourceRoot":"","sources":["../src/summaryFormat.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 { assert } from \"@fluidframework/common-utils\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { channelsTreeName, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\n\ntype OmitAttributesVersions<T> = Omit<T, \"snapshotFormatVersion\" | \"summaryFormatVersion\">;\ninterface IFluidDataStoreAttributes0 {\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion?: undefined;\n pkg: string;\n /**\n * This tells whether a data store is root. Root data stores are never collected.\n * Non-root data stores may be collected if they are not used. If this is not present, default it to\n * true. This will ensure that older data stores are incorrectly collected.\n */\n readonly isRootDataStore?: boolean;\n}\ninterface IFluidDataStoreAttributes1 extends OmitAttributesVersions<IFluidDataStoreAttributes0> {\n readonly snapshotFormatVersion: \"0.1\";\n readonly summaryFormatVersion?: undefined;\n}\ninterface IFluidDataStoreAttributes2 extends OmitAttributesVersions<IFluidDataStoreAttributes1> {\n /** Switch from snapshotFormatVersion to summaryFormatVersion */\n readonly snapshotFormatVersion?: undefined;\n readonly summaryFormatVersion: 2;\n /**\n * True if channels are not isolated in .channels subtrees, otherwise isolated.\n * This is required in both datastore attributes as well as the root container,\n * because reused summary handles may cause different format versions in each\n * datastore subtree within the summary.\n */\n readonly disableIsolatedChannels?: true;\n}\n/**\n * Added IFluidDataStoreAttributes similar to IChannelAttributes which will tell the attributes of a\n * store like the package, snapshotFormatVersion to take different decisions based on a particular\n * snapshotFormatVersion.\n */\nexport type ReadFluidDataStoreAttributes =\n | IFluidDataStoreAttributes0\n | IFluidDataStoreAttributes1\n | IFluidDataStoreAttributes2;\nexport type WriteFluidDataStoreAttributes = IFluidDataStoreAttributes1 | IFluidDataStoreAttributes2;\n\nexport function getAttributesFormatVersion(attributes: ReadFluidDataStoreAttributes): number {\n if (attributes.summaryFormatVersion) {\n /**\n * Version 2+: Introduces .channels trees for isolation of\n * channel trees from data store objects.\n */\n return attributes.summaryFormatVersion;\n } else if (attributes.snapshotFormatVersion === \"0.1\") {\n /**\n * Version 1: from this version the pkg within the data store\n * attributes blob is a JSON array rather than a string.\n */\n return 1;\n }\n /**\n * Version 0: format version is missing from summary.\n * This indicates it is an older version.\n */\n return 0;\n}\n\nexport function hasIsolatedChannels(attributes: ReadFluidDataStoreAttributes): boolean {\n return !!attributes.summaryFormatVersion && !attributes.disableIsolatedChannels;\n}\n\nexport type GCVersion = number;\nexport interface IContainerRuntimeMetadata extends ICreateContainerMetadata {\n readonly summaryFormatVersion: 1;\n /** The last message processed at the time of summary. Only primitive propertiy types are added to the summary. */\n readonly message: ISummaryMetadataMessage | undefined;\n /** True if channels are not isolated in .channels subtrees, otherwise isolated. */\n readonly disableIsolatedChannels?: true;\n /** 0 to disable GC, > 0 to enable GC, undefined defaults to disabled. */\n readonly gcFeature?: GCVersion;\n /** Counter of the last summary happened, increments every time we summarize */\n readonly summaryCount?: number;\n /** If this is present, the session for this container will expire after this time and the container will close */\n readonly sessionExpiryTimeoutMs?: number;\n}\n\nexport interface ICreateContainerMetadata {\n /** Runtime version of the container when it was first created */\n createContainerRuntimeVersion?: string;\n /** Timestamp of the container when it was first created */\n createContainerTimestamp?: number;\n}\n\n/** The properties of an ISequencedDocumentMessage to be stored in the metadata blob in summary. */\nexport type ISummaryMetadataMessage = Pick<ISequencedDocumentMessage,\n | \"clientId\"\n | \"clientSequenceNumber\"\n | \"minimumSequenceNumber\"\n | \"referenceSequenceNumber\"\n | \"sequenceNumber\"\n | \"timestamp\"\n | \"type\">;\n\n/**\n * Extracts the properties from an ISequencedDocumentMessage as defined by ISummaryMetadataMessage. This message is\n * added to the metadata blob in summary.\n */\nexport const extractSummaryMetadataMessage = (\n message?: ISequencedDocumentMessage,\n): ISummaryMetadataMessage | undefined => message === undefined ? undefined : {\n clientId: message.clientId,\n clientSequenceNumber: message.clientSequenceNumber,\n minimumSequenceNumber: message.minimumSequenceNumber,\n referenceSequenceNumber: message.referenceSequenceNumber,\n sequenceNumber: message.sequenceNumber,\n timestamp: message.timestamp,\n type: message.type,\n};\n\nexport function getMetadataFormatVersion(metadata?: IContainerRuntimeMetadata): number {\n /**\n * Version 2+: Introduces runtime sequence number for data verification.\n *\n * Version 1+: Introduces .metadata blob and .channels trees for isolation of\n * data store trees from container-level objects.\n * Also introduces enableGC option stored in the summary.\n *\n * Version 0: metadata blob missing; format version is missing from summary.\n * This indicates it is an older version.\n */\n return metadata?.summaryFormatVersion ?? 0;\n}\n\nexport const aliasBlobName = \".aliases\";\nexport const metadataBlobName = \".metadata\";\nexport const chunksBlobName = \".chunks\";\nexport const electedSummarizerBlobName = \".electedSummarizer\";\nexport const blobsTreeName = \".blobs\";\n\nexport function rootHasIsolatedChannels(metadata?: IContainerRuntimeMetadata): boolean {\n return !!metadata && !metadata.disableIsolatedChannels;\n}\n\nexport function getGCVersion(metadata?: IContainerRuntimeMetadata): GCVersion {\n if (!metadata) {\n // Force to 0/disallowed in prior versions\n return 0;\n }\n return metadata.gcFeature ?? 0;\n}\n\nexport const protocolTreeName = \".protocol\";\n\n/**\n * List of tree IDs at the container level which are reserved.\n * This is for older versions of summaries that do not yet have an\n * isolated data stores namespace. Without the namespace, this must\n * be used to prevent name collisions with data store IDs.\n */\nexport const nonDataStorePaths = [protocolTreeName, \".logTail\", \".serviceProtocol\", blobsTreeName];\n\nexport const dataStoreAttributesBlobName = \".component\";\n\n/**\n * Modifies summary tree and stats to put tree under .channels tree.\n * Converts from: {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} },\n * }\n * to: {\n * type: SummaryType.Tree,\n * tree: {\n * \".channels\": {\n * type: SummaryType.Tree,\n * tree: { a: {...}, b: {...}, c: {...} }\n * },\n * },\n * }\n * And adds +1 to treeNodeCount in stats.\n * @param summarizeResult - summary tree and stats to modify\n */\nexport function wrapSummaryInChannelsTree(summarizeResult: ISummaryTreeWithStats): void {\n summarizeResult.summary = {\n type: SummaryType.Tree,\n tree: { [channelsTreeName]: summarizeResult.summary },\n };\n summarizeResult.stats.treeNodeCount++;\n}\n\nexport async function getFluidDataStoreAttributes(\n storage: IDocumentStorageService,\n snapshot: ISnapshotTree,\n): Promise<ReadFluidDataStoreAttributes> {\n const attributes = await readAndParse<ReadFluidDataStoreAttributes>(\n storage, snapshot.blobs[dataStoreAttributesBlobName]);\n // Use the snapshotFormatVersion to determine how the pkg is encoded in the snapshot.\n // For snapshotFormatVersion = \"0.1\" (1) or above, pkg is jsonified, otherwise it is just a string.\n // However the feature of loading a detached container from snapshot, is added when the\n // snapshotFormatVersion is at least \"0.1\" (1), so we don't expect it to be anything else.\n const formatVersion = getAttributesFormatVersion(attributes);\n assert(formatVersion > 0,\n 0x1d5 /* `Invalid snapshot format version ${attributes.snapshotFormatVersion}` */);\n return attributes;\n}\n"]}
@@ -76,6 +76,7 @@ export declare class SummaryManager extends TypedEventEmitter<ISummaryManagerEve
76
76
  start(): void;
77
77
  private readonly handleConnected;
78
78
  private readonly handleDisconnected;
79
+ private static readonly isStartingOrRunning;
79
80
  private getShouldSummarizeState;
80
81
  private readonly refreshSummarizer;
81
82
  private startSummarization;
@@ -1 +1 @@
1
- {"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../src/summaryManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../src/summaryManager.ts"],"names":[],"mappings":"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"}
@@ -173,7 +173,9 @@ export class SummaryManager extends TypedEventEmitter {
173
173
  // Note that summarizer may keep going (like doing last summary).
174
174
  // Ideally we await stopping process, but this code path is due to a bug
175
175
  // that needs to be fixed either way.
176
- this.stop("summarizerException");
176
+ if (SummaryManager.isStartingOrRunning(this.state)) {
177
+ this.stop("summarizerException");
178
+ }
177
179
  }
178
180
  }).finally(() => {
179
181
  assert(this.state !== SummaryManagerState.Off, 0x264 /* "Expected: Not Off" */);
@@ -190,7 +192,9 @@ export class SummaryManager extends TypedEventEmitter {
190
192
  }
191
193
  stop(reason) {
192
194
  var _a;
193
- assert(this.state === SummaryManagerState.Running || this.state === SummaryManagerState.Starting, 0x265 /* "Expected: Starting or Running" */);
195
+ if (!SummaryManager.isStartingOrRunning(this.state)) {
196
+ return;
197
+ }
194
198
  this.state = SummaryManagerState.Stopping;
195
199
  // Stopping the running summarizer client should trigger a change
196
200
  // in states when the running summarizer closes
@@ -259,4 +263,5 @@ export class SummaryManager extends TypedEventEmitter {
259
263
  this._disposed = true;
260
264
  }
261
265
  }
266
+ SummaryManager.isStartingOrRunning = (state) => state === SummaryManagerState.Starting || state === SummaryManagerState.Running;
262
267
  //# sourceMappingURL=summaryManager.js.map