@fluidframework/container-runtime 0.55.0-48551 → 0.56.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.
- package/dist/containerRuntime.d.ts +3 -12
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +22 -38
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +42 -29
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +27 -49
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +2 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +74 -16
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +22 -9
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +55 -32
- package/dist/garbageCollection.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -17
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +2 -9
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +2 -1
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts +0 -5
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js.map +1 -1
- package/garbageCollection.md +33 -0
- package/lib/containerRuntime.d.ts +3 -12
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +23 -39
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +42 -29
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +25 -47
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +2 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +75 -17
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +22 -9
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +55 -32
- package/lib/garbageCollection.js.map +1 -1
- package/lib/index.d.ts +6 -6
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -6
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +2 -9
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +2 -1
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts +0 -5
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js.map +1 -1
- package/package.json +15 -15
- package/src/containerRuntime.ts +36 -42
- package/src/dataStoreContext.ts +76 -122
- package/src/dataStores.ts +75 -48
- package/src/garbageCollection.ts +62 -35
- package/src/index.ts +51 -6
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +2 -7
- package/src/summaryFormat.ts +2 -1
- package/src/summaryGenerator.ts +0 -5
package/lib/dataStores.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataStores.js","sourceRoot":"","sources":["../src/dataStores.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, ITelemetryBaseLogger, IDisposable } from \"@fluidframework/common-definitions\";\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { FluidObjectHandle } from \"@fluidframework/datastore\";\nimport {\n ISequencedDocumentMessage,\n ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n channelsTreeName,\n CreateChildSummarizerNodeFn,\n CreateChildSummarizerNodeParam,\n CreateSummarizerNodeSource,\n IAttachMessage,\n IEnvelope,\n IFluidDataStoreChannel,\n IFluidDataStoreContextDetached,\n IGarbageCollectionData,\n IGarbageCollectionDetailsBase,\n IInboundSignalMessage,\n InboundAttachMessage,\n ISummarizeResult,\n ISummaryTreeWithStats,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n convertSnapshotTreeToSummaryTree,\n convertToSummaryTree,\n create404Response,\n responseToException,\n SummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils\";\nimport { ChildLogger, TelemetryDataTag } from \"@fluidframework/telemetry-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { BlobCacheStorageService, buildSnapshotTree } from \"@fluidframework/driver-utils\";\nimport { assert, Lazy, LazyPromise } from \"@fluidframework/common-utils\";\nimport { v4 as uuid } from \"uuid\";\nimport { GCDataBuilder, unpackChildNodesUsedRoutes } from \"@fluidframework/garbage-collector\";\nimport { DataStoreContexts } from \"./dataStoreContexts\";\nimport { ContainerRuntime } from \"./containerRuntime\";\nimport {\n FluidDataStoreContext,\n RemotedFluidDataStoreContext,\n LocalFluidDataStoreContext,\n createAttributesBlob,\n LocalDetachedFluidDataStoreContext,\n} from \"./dataStoreContext\";\nimport { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from \"./summaryFormat\";\nimport { IUsedStateStats } from \"./garbageCollection\";\n\ntype PendingAliasResolve = (success: boolean) => void;\n\n/**\n * Interface for an op to be used for assigning an\n * alias to a datastore\n */\ninterface IDataStoreAliasMessage {\n /** The internal id of the datastore */\n readonly internalId: string;\n /** The alias name to be assigned to the datastore */\n readonly alias: string;\n}\n\n/**\n * Type guard that returns true if the given alias message is actually an instance of\n * a class which implements @see IDataStoreAliasMessage\n * @param maybeDataStoreAliasMessage - message object to be validated\n * @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise\n */\nconst isDataStoreAliasMessage = (\n maybeDataStoreAliasMessage: any,\n): maybeDataStoreAliasMessage is IDataStoreAliasMessage => {\n return typeof maybeDataStoreAliasMessage?.internalId === \"string\"\n && typeof maybeDataStoreAliasMessage?.alias === \"string\";\n};\n\n /**\n * This class encapsulates data store handling. Currently it is only used by the container runtime,\n * but eventually could be hosted on any channel once we formalize the channel api boundary.\n */\nexport class DataStores implements IDisposable {\n // Stores tracked by the Domain\n private readonly pendingAttach = new Map<string, IAttachMessage>();\n // 0.24 back-compat attachingBeforeSummary\n public readonly attachOpFiredForDataStore = new Set<string>();\n\n private readonly logger: ITelemetryLogger;\n\n private readonly disposeOnce = new Lazy<void>(() => this.contexts.dispose());\n\n public readonly containerLoadStats: {\n // number of dataStores during loadContainer\n readonly containerLoadDataStoreCount: number;\n // number of unreferenced dataStores during loadContainer\n readonly referencedDataStoreCount: number;\n };\n\n // Stores the ids of new data stores between two GC runs. This is used to notify the garbage collector of new\n // root data stores that are added.\n private dataStoresSinceLastGC: string[] = [];\n // The handle to the container runtime. This is used mainly for GC purposes to represent outbound reference from\n // the container runtime to other nodes.\n private readonly containerRuntimeHandle: IFluidHandle;\n\n constructor(\n private readonly baseSnapshot: ISnapshotTree | undefined,\n private readonly runtime: ContainerRuntime,\n private readonly submitAttachFn: (attachContent: any) => void,\n private readonly getCreateChildSummarizerNodeFn:\n (id: string, createParam: CreateChildSummarizerNodeParam) => CreateChildSummarizerNodeFn,\n private readonly deleteChildSummarizerNodeFn: (id: string) => void,\n baseLogger: ITelemetryBaseLogger,\n getBaseGCDetails: () => Promise<Map<string, IGarbageCollectionDetailsBase>>,\n private readonly dataStoreChanged: (id: string) => void,\n private readonly aliasMap: Map<string, string>,\n private readonly contexts: DataStoreContexts = new DataStoreContexts(baseLogger),\n ) {\n this.logger = ChildLogger.create(baseLogger);\n this.containerRuntimeHandle = new FluidObjectHandle(this.runtime, \"/\", this.runtime.IFluidHandleContext);\n\n const baseGCDetailsP = new LazyPromise(async () => {\n return getBaseGCDetails();\n });\n // Returns the base GC details for the data store with the given id.\n const dataStoreBaseGCDetails = async (dataStoreId: string) => {\n const baseGCDetails = await baseGCDetailsP;\n return baseGCDetails.get(dataStoreId);\n };\n\n // Extract stores stored inside the snapshot\n const fluidDataStores = new Map<string, ISnapshotTree>();\n if (baseSnapshot) {\n for (const [key, value] of Object.entries(baseSnapshot.trees)) {\n fluidDataStores.set(key, value);\n }\n }\n\n let unreferencedDataStoreCount = 0;\n // Create a context for each of them\n for (const [key, value] of fluidDataStores) {\n let dataStoreContext: FluidDataStoreContext;\n\n // counting number of unreferenced data stores\n if (value.unreferenced) {\n unreferencedDataStoreCount++;\n }\n // If we have a detached container, then create local data store contexts.\n if (this.runtime.attachState !== AttachState.Detached) {\n dataStoreContext = new RemotedFluidDataStoreContext(\n key,\n value,\n async () => dataStoreBaseGCDetails(key),\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }));\n } else {\n if (typeof value !== \"object\") {\n throw new Error(\"Snapshot should be there to load from!!\");\n }\n const snapshotTree = value;\n dataStoreContext = new LocalFluidDataStoreContext(\n key,\n undefined,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n snapshotTree,\n undefined,\n );\n }\n this.contexts.addBoundOrRemoted(dataStoreContext);\n }\n this.containerLoadStats = {\n containerLoadDataStoreCount: fluidDataStores.size,\n referencedDataStoreCount: fluidDataStores.size - unreferencedDataStoreCount,\n };\n }\n\n public aliases(): ReadonlyMap<string, string> {\n return this.aliasMap;\n }\n\n public processAttachMessage(message: ISequencedDocumentMessage, local: boolean) {\n const attachMessage = message.contents as InboundAttachMessage;\n\n this.dataStoresSinceLastGC.push(attachMessage.id);\n\n // The local object has already been attached\n if (local) {\n assert(this.pendingAttach.has(attachMessage.id),\n 0x15e /* \"Local object does not have matching attach message id\" */);\n this.contexts.get(attachMessage.id)?.emit(\"attached\");\n this.pendingAttach.delete(attachMessage.id);\n return;\n }\n\n // If a non-local operation then go and create the object, otherwise mark it as officially attached.\n if (this.alreadyProcessed(attachMessage.id)) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n const error = new DataCorruptionError(\n \"duplicateDataStoreCreatedWithExistingId\",\n {\n ...extractSafePropertiesFromMessage(message),\n dataStoreId: {\n value: attachMessage.id,\n tag: TelemetryDataTag.PackageData,\n },\n },\n );\n throw error;\n }\n\n const flatBlobs = new Map<string, ArrayBufferLike>();\n let snapshotTree: ISnapshotTree | undefined;\n if (attachMessage.snapshot) {\n snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);\n }\n\n // Include the type of attach message which is the pkg of the store to be\n // used by RemotedFluidDataStoreContext in case it is not in the snapshot.\n const pkg = [attachMessage.type];\n const remotedFluidDataStoreContext = new RemotedFluidDataStoreContext(\n attachMessage.id,\n snapshotTree,\n // New data stores begin with empty GC details since GC hasn't run on them yet.\n async () => { return {}; },\n this.runtime,\n new BlobCacheStorageService(this.runtime.storage, flatBlobs),\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(\n attachMessage.id,\n {\n type: CreateSummarizerNodeSource.FromAttach,\n sequenceNumber: message.sequenceNumber,\n snapshot: attachMessage.snapshot ?? {\n entries: [createAttributesBlob(\n pkg,\n true /* isRootDataStore */,\n this.runtime.disableIsolatedChannels,\n )],\n },\n }),\n pkg);\n\n this.contexts.addBoundOrRemoted(remotedFluidDataStoreContext);\n }\n\n public processAliasMessage(\n message: ISequencedDocumentMessage,\n localOpMetadata: unknown,\n local: boolean,\n ): void {\n const aliasMessage = message.contents as IDataStoreAliasMessage;\n if (!isDataStoreAliasMessage(aliasMessage)) {\n throw new DataCorruptionError(\n \"malformedDataStoreAliasMessage\",\n {\n ...extractSafePropertiesFromMessage(message),\n },\n );\n }\n\n const resolve = localOpMetadata as PendingAliasResolve;\n const aliasResult = this.processAliasMessageCore(aliasMessage);\n if (local) {\n resolve(aliasResult);\n }\n }\n\n private processAliasMessageCore(aliasMessage: IDataStoreAliasMessage): boolean {\n if (this.alreadyProcessed(aliasMessage.alias)) {\n return false;\n }\n\n const currentContext = this.contexts.get(aliasMessage.internalId);\n if (currentContext === undefined) {\n this.logger.sendErrorEvent({\n eventName: \"AliasFluidDataStoreNotFound\",\n fluidDataStoreId: aliasMessage.internalId,\n });\n return false;\n }\n\n this.aliasMap.set(aliasMessage.alias, currentContext.id);\n currentContext.setRoot();\n return true;\n }\n\n private alreadyProcessed(id: string): boolean {\n return this.aliasMap.get(id) !== undefined || this.contexts.get(id) !== undefined;\n }\n\n public bindFluidDataStore(fluidDataStoreRuntime: IFluidDataStoreChannel): void {\n const id = fluidDataStoreRuntime.id;\n const localContext = this.contexts.getUnbound(id);\n assert(!!localContext, 0x15f /* \"Could not find unbound context to bind\" */);\n\n // If the container is detached, we don't need to send OP or add to pending attach because\n // we will summarize it while uploading the create new summary and make it known to other\n // clients.\n if (this.runtime.attachState !== AttachState.Detached) {\n localContext.emit(\"attaching\");\n const message = localContext.generateAttachMessage();\n\n this.pendingAttach.set(id, message);\n this.submitAttachFn(message);\n this.attachOpFiredForDataStore.add(id);\n }\n\n this.contexts.bind(fluidDataStoreRuntime.id);\n }\n\n public createDetachedDataStoreCore(\n pkg: Readonly<string[]>,\n isRoot: boolean,\n id = uuid()): IFluidDataStoreContextDetached\n {\n const context = new LocalDetachedFluidDataStoreContext(\n id,\n pkg,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(id, { type: CreateSummarizerNodeSource.Local }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n isRoot,\n );\n this.contexts.addUnbound(context);\n return context;\n }\n\n public _createFluidDataStoreContext(pkg: string[], id: string, isRoot: boolean, props?: any) {\n const context = new LocalFluidDataStoreContext(\n id,\n pkg,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(id, { type: CreateSummarizerNodeSource.Local }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n undefined,\n isRoot,\n props,\n );\n this.contexts.addUnbound(context);\n return context;\n }\n\n public get disposed() {return this.disposeOnce.evaluated;}\n public readonly dispose = () => this.disposeOnce.value;\n\n public resubmitDataStoreOp(content: any, localOpMetadata: unknown) {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x160 /* \"There should be a store context for the op\" */);\n context.reSubmit(envelope.contents, localOpMetadata);\n }\n\n public async applyStashedOp(content: any): Promise<unknown> {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x161 /* \"There should be a store context for the op\" */);\n return context.applyStashedOp(envelope.contents);\n }\n\n public async applyStashedAttachOp(message: IAttachMessage) {\n this.pendingAttach.set(message.id, message);\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n this.processAttachMessage({ contents: message } as ISequencedDocumentMessage, false);\n }\n\n public processFluidDataStoreOp(message: ISequencedDocumentMessage, local: boolean, localMessageMetadata: unknown) {\n const envelope = message.contents as IEnvelope;\n const transformed = { ...message, contents: envelope.contents };\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x162 /* \"There should be a store context for the op\" */);\n context.process(transformed, local, localMessageMetadata);\n\n // Notify that a data store changed. This is used to detect if a deleted data store is being used.\n this.dataStoreChanged(envelope.address);\n }\n\n public async getDataStore(id: string, wait: boolean): Promise<FluidDataStoreContext> {\n const internalId = this.aliasMap.get(id) ?? id;\n\n const context = await this.contexts.getBoundOrRemoted(internalId, wait);\n if (context === undefined) {\n // The requested data store does not exits. Throw a 404 response exception.\n const request = { url: id };\n throw responseToException(create404Response(request), request);\n }\n\n return context;\n }\n\n public processSignal(address: string, message: IInboundSignalMessage, local: boolean) {\n const context = this.contexts.get(address);\n if (!context) {\n // Attach message may not have been processed yet\n assert(!local, 0x163 /* \"Missing datastore for local signal\" */);\n this.logger.sendTelemetryEvent({\n eventName: \"SignalFluidDataStoreNotFound\",\n fluidDataStoreId: address,\n });\n return;\n }\n\n context.processSignal(message, local);\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n for (const [fluidDataStore, context] of this.contexts) {\n try {\n context.setConnectionState(connected, clientId);\n } catch (error) {\n this.logger.sendErrorEvent({\n eventName: \"SetConnectionStateError\",\n clientId,\n fluidDataStore,\n }, error);\n }\n }\n }\n\n public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {\n let eventName: \"attaching\" | \"attached\";\n if (attachState === AttachState.Attaching) {\n eventName = \"attaching\";\n } else {\n eventName = \"attached\";\n }\n for (const [,context] of this.contexts) {\n // Fire only for bounded stores.\n if (!this.contexts.isNotBound(context.id)) {\n context.emit(eventName);\n }\n }\n }\n\n public get size(): number {\n return this.contexts.size;\n }\n\n public async summarize(fullTree: boolean, trackState: boolean): Promise<ISummaryTreeWithStats> {\n const summaryBuilder = new SummaryTreeBuilder();\n\n // Iterate over each store and ask it to snapshot\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Summarizer works only with clients with no local changes!\n assert(context.attachState !== AttachState.Attaching,\n 0x165 /* \"Summarizer cannot work if client has local changes\" */);\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextSummary = await context.summarize(fullTree, trackState);\n summaryBuilder.addWithStats(contextId, contextSummary);\n }));\n\n return summaryBuilder.getSummaryTree();\n }\n\n public createSummary(): ISummaryTreeWithStats {\n const builder = new SummaryTreeBuilder();\n // Attaching graph of some stores can cause other stores to get bound too.\n // So keep taking summary until no new stores get bound.\n let notBoundContextsLength: number;\n do {\n const builderTree = builder.summary.tree;\n notBoundContextsLength = this.contexts.notBoundLength();\n // Iterate over each data store and ask it to snapshot\n Array.from(this.contexts)\n .filter(([key, _]) =>\n // Take summary of bounded data stores only, make sure we haven't summarized them already\n // and no attach op has been fired for that data store because for loader versions <= 0.24\n // we set attach state as \"attaching\" before taking createNew summary.\n !(this.contexts.isNotBound(key)\n || builderTree[key]\n || this.attachOpFiredForDataStore.has(key)),\n )\n .map(([key, value]) => {\n let dataStoreSummary: ISummarizeResult;\n if (value.isLoaded) {\n const snapshot = value.generateAttachMessage().snapshot;\n dataStoreSummary = convertToSummaryTree(snapshot, true);\n } else {\n // If this data store is not yet loaded, then there should be no changes in the snapshot from\n // which it was created as it is detached container. So just use the previous snapshot.\n assert(!!this.baseSnapshot,\n 0x166 /* \"BaseSnapshot should be there as detached container loaded from snapshot\" */);\n dataStoreSummary = convertSnapshotTreeToSummaryTree(this.baseSnapshot.trees[key]);\n }\n builder.addWithStats(key, dataStoreSummary);\n });\n } while (notBoundContextsLength !== this.contexts.notBoundLength());\n\n return builder.getSummaryTree();\n }\n\n /**\n * Before GC runs, called by the garbage collector to update any pending GC state.\n * The garbage collector needs to know all outbound references that are added. Since root data stores are not\n * explicitly marked as referenced, notify GC of new root data stores that were added since the last GC run.\n */\n public async updateStateBeforeGC(): Promise<void> {\n for (const id of this.dataStoresSinceLastGC) {\n const context = this.contexts.get(id);\n assert(context !== undefined, 0x2b6 /* `Missing data store context with id ${id}` */);\n if (await context.isRoot()) {\n // A root data store is basically a reference from the container runtime to the data store.\n const handle = new FluidObjectHandle(context, id, this.runtime.IFluidHandleContext);\n this.runtime.addedGCOutboundReference(this.containerRuntimeHandle, handle);\n }\n }\n this.dataStoresSinceLastGC = [];\n }\n\n /**\n * Generates data used for garbage collection. It does the following:\n * 1. Calls into each child data store context to get its GC data.\n * 2. Prefixes the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be\n * identified as belonging to the child.\n * 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent\n * the GC data of this channel.\n * @param fullGC - true to bypass optimizations and force full generation of GC data.\n */\n public async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n const builder = new GCDataBuilder();\n // Iterate over each store and get their GC data.\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Get GC data only for attached contexts. Detached contexts are not connected in the GC reference\n // graph so any references they might have won't be connected as well.\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextGCData = await context.getGCData(fullGC);\n // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.\n // This also gradually builds the id of each node to be a path from the root.\n builder.prefixAndAddNodes(contextId, contextGCData.gcNodes);\n }));\n\n // Get the outbound routes and add a GC node for this channel.\n builder.addNode(\"/\", await this.getOutboundRoutes());\n return builder.getGCData();\n }\n\n /**\n * After GC has run, called to notify this Container's data stores of routes that are used in it.\n * @param usedRoutes - The routes that are used in all data stores in this Container.\n * @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes\n * unreferenced as part of this GC run, this should be used to update the time when it happens.\n * @returns the statistics of the used state of the data stores.\n */\n public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): IUsedStateStats {\n // Get a map of data store ids to routes used in it.\n const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);\n\n // Verify that the used routes are correct.\n for (const [id] of usedDataStoreRoutes) {\n assert(this.contexts.has(id), 0x167 /* \"Used route does not belong to any known data store\" */);\n }\n\n // Update the used routes in each data store. Used routes is empty for unused data stores.\n for (const [contextId, context] of this.contexts) {\n context.updateUsedRoutes(usedDataStoreRoutes.get(contextId) ?? [], gcTimestamp);\n }\n\n // Return the number of data stores that are unused.\n const dataStoreCount = this.contexts.size;\n return {\n totalNodeCount: dataStoreCount,\n unusedNodeCount: dataStoreCount - usedDataStoreRoutes.size,\n };\n }\n\n /**\n * When running GC in test mode, this is called to delete objects whose routes are unused. This enables testing\n * scenarios with accessing deleted content.\n * @param unusedRoutes - The routes that are unused in all data stores in this Container.\n */\n public deleteUnusedRoutes(unusedRoutes: string[]) {\n for (const route of unusedRoutes) {\n const dataStoreId = route.split(\"/\")[1];\n // Delete the contexts of unused data stores.\n this.contexts.delete(dataStoreId);\n // Delete the summarizer node of the unused data stores.\n this.deleteChildSummarizerNodeFn(dataStoreId);\n }\n }\n\n /**\n * Returns the outbound routes of this channel. Only root data stores are considered referenced and their paths are\n * part of outbound routes.\n */\n private async getOutboundRoutes(): Promise<string[]> {\n const outboundRoutes: string[] = [];\n for (const [contextId, context] of this.contexts) {\n const isRootDataStore = await context.isRoot();\n if (isRootDataStore) {\n outboundRoutes.push(`/${contextId}`);\n }\n }\n return outboundRoutes;\n }\n}\n\nexport function getSummaryForDatastores(\n snapshot: ISnapshotTree | undefined,\n metadata?: IContainerRuntimeMetadata,\n): ISnapshotTree | undefined {\n if (!snapshot) {\n return undefined;\n }\n\n if (rootHasIsolatedChannels(metadata)) {\n const datastoresSnapshot = snapshot.trees[channelsTreeName];\n assert(!!datastoresSnapshot, 0x168 /* `expected ${channelsTreeName} tree in snapshot` */);\n return datastoresSnapshot;\n } else {\n // back-compat: strip out all non-datastore paths before giving to DataStores object.\n const datastoresTrees: ISnapshotTree[\"trees\"] = {};\n for (const [key, value] of Object.entries(snapshot.trees)) {\n if (!nonDataStorePaths.includes(key)) {\n datastoresTrees[key] = value;\n }\n }\n return {\n ...snapshot,\n trees: datastoresTrees,\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dataStores.js","sourceRoot":"","sources":["../src/dataStores.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, ITelemetryBaseLogger, IDisposable } from \"@fluidframework/common-definitions\";\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { FluidObjectHandle } from \"@fluidframework/datastore\";\nimport {\n ISequencedDocumentMessage,\n ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n channelsTreeName,\n CreateChildSummarizerNodeFn,\n CreateChildSummarizerNodeParam,\n CreateSummarizerNodeSource,\n IAttachMessage,\n IEnvelope,\n IFluidDataStoreChannel,\n IFluidDataStoreContextDetached,\n IGarbageCollectionData,\n IGarbageCollectionDetailsBase,\n IInboundSignalMessage,\n InboundAttachMessage,\n ISummarizeResult,\n ISummaryTreeWithStats,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n convertSnapshotTreeToSummaryTree,\n convertToSummaryTree,\n create404Response,\n responseToException,\n SummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils\";\nimport { ChildLogger, TelemetryDataTag } from \"@fluidframework/telemetry-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { BlobCacheStorageService, buildSnapshotTree } from \"@fluidframework/driver-utils\";\nimport { assert, Lazy, LazyPromise } from \"@fluidframework/common-utils\";\nimport { v4 as uuid } from \"uuid\";\nimport { GCDataBuilder, unpackChildNodesUsedRoutes } from \"@fluidframework/garbage-collector\";\nimport { DataStoreContexts } from \"./dataStoreContexts\";\nimport { ContainerRuntime } from \"./containerRuntime\";\nimport {\n FluidDataStoreContext,\n RemoteFluidDataStoreContext,\n LocalFluidDataStoreContext,\n createAttributesBlob,\n LocalDetachedFluidDataStoreContext,\n} from \"./dataStoreContext\";\nimport { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from \"./summaryFormat\";\nimport { IUsedStateStats } from \"./garbageCollection\";\n\ntype PendingAliasResolve = (success: boolean) => void;\n\n/**\n * Interface for an op to be used for assigning an\n * alias to a datastore\n */\ninterface IDataStoreAliasMessage {\n /** The internal id of the datastore */\n readonly internalId: string;\n /** The alias name to be assigned to the datastore */\n readonly alias: string;\n}\n\n/**\n * Type guard that returns true if the given alias message is actually an instance of\n * a class which implements @see IDataStoreAliasMessage\n * @param maybeDataStoreAliasMessage - message object to be validated\n * @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise\n */\nconst isDataStoreAliasMessage = (\n maybeDataStoreAliasMessage: any,\n): maybeDataStoreAliasMessage is IDataStoreAliasMessage => {\n return typeof maybeDataStoreAliasMessage?.internalId === \"string\"\n && typeof maybeDataStoreAliasMessage?.alias === \"string\";\n};\n\n /**\n * This class encapsulates data store handling. Currently it is only used by the container runtime,\n * but eventually could be hosted on any channel once we formalize the channel api boundary.\n */\nexport class DataStores implements IDisposable {\n // Stores tracked by the Domain\n private readonly pendingAttach = new Map<string, IAttachMessage>();\n // 0.24 back-compat attachingBeforeSummary\n public readonly attachOpFiredForDataStore = new Set<string>();\n\n private readonly logger: ITelemetryLogger;\n\n private readonly disposeOnce = new Lazy<void>(() => this.contexts.dispose());\n\n public readonly containerLoadStats: {\n // number of dataStores during loadContainer\n readonly containerLoadDataStoreCount: number;\n // number of unreferenced dataStores during loadContainer\n readonly referencedDataStoreCount: number;\n };\n\n // Stores the ids of new data stores between two GC runs. This is used to notify the garbage collector of new\n // root data stores that are added.\n private dataStoresSinceLastGC: string[] = [];\n // The handle to the container runtime. This is used mainly for GC purposes to represent outbound reference from\n // the container runtime to other nodes.\n private readonly containerRuntimeHandle: IFluidHandle;\n\n constructor(\n private readonly baseSnapshot: ISnapshotTree | undefined,\n private readonly runtime: ContainerRuntime,\n private readonly submitAttachFn: (attachContent: any) => void,\n private readonly getCreateChildSummarizerNodeFn:\n (id: string, createParam: CreateChildSummarizerNodeParam) => CreateChildSummarizerNodeFn,\n private readonly deleteChildSummarizerNodeFn: (id: string) => void,\n baseLogger: ITelemetryBaseLogger,\n getBaseGCDetails: () => Promise<Map<string, IGarbageCollectionDetailsBase>>,\n private readonly dataStoreChanged: (id: string) => void,\n private readonly aliasMap: Map<string, string>,\n private readonly writeGCDataAtRoot: boolean,\n private readonly contexts: DataStoreContexts = new DataStoreContexts(baseLogger),\n ) {\n this.logger = ChildLogger.create(baseLogger);\n this.containerRuntimeHandle = new FluidObjectHandle(this.runtime, \"/\", this.runtime.IFluidHandleContext);\n\n const baseGCDetailsP = new LazyPromise(async () => {\n return getBaseGCDetails();\n });\n // Returns the base GC details for the data store with the given id.\n const dataStoreBaseGCDetails = async (dataStoreId: string) => {\n const baseGCDetails = await baseGCDetailsP;\n return baseGCDetails.get(dataStoreId);\n };\n\n // Extract stores stored inside the snapshot\n const fluidDataStores = new Map<string, ISnapshotTree>();\n if (baseSnapshot) {\n for (const [key, value] of Object.entries(baseSnapshot.trees)) {\n fluidDataStores.set(key, value);\n }\n }\n\n let unreferencedDataStoreCount = 0;\n // Create a context for each of them\n for (const [key, value] of fluidDataStores) {\n let dataStoreContext: FluidDataStoreContext;\n\n // counting number of unreferenced data stores\n if (value.unreferenced) {\n unreferencedDataStoreCount++;\n }\n // If we have a detached container, then create local data store contexts.\n if (this.runtime.attachState !== AttachState.Detached) {\n dataStoreContext = new RemoteFluidDataStoreContext({\n id: key,\n snapshotTree: value,\n getBaseGCDetails: async () => dataStoreBaseGCDetails(key),\n runtime: this.runtime,\n storage: this.runtime.storage,\n scope: this.runtime.scope,\n createSummarizerNodeFn: this.getCreateChildSummarizerNodeFn(\n key,\n { type: CreateSummarizerNodeSource.FromSummary },\n ),\n writeGCDataAtRoot: this.writeGCDataAtRoot,\n disableIsolatedChannels: this.runtime.disableIsolatedChannels,\n });\n } else {\n if (typeof value !== \"object\") {\n throw new Error(\"Snapshot should be there to load from!!\");\n }\n const snapshotTree = value;\n dataStoreContext = new LocalFluidDataStoreContext({\n id: key,\n pkg: undefined,\n runtime: this.runtime,\n storage: this.runtime.storage,\n scope: this.runtime.scope,\n createSummarizerNodeFn: this.getCreateChildSummarizerNodeFn(\n key,\n { type: CreateSummarizerNodeSource.FromSummary },\n ),\n bindChannelFn: (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n snapshotTree,\n isRootDataStore: undefined,\n writeGCDataAtRoot: this.writeGCDataAtRoot,\n disableIsolatedChannels: this.runtime.disableIsolatedChannels,\n });\n }\n this.contexts.addBoundOrRemoted(dataStoreContext);\n }\n this.containerLoadStats = {\n containerLoadDataStoreCount: fluidDataStores.size,\n referencedDataStoreCount: fluidDataStores.size - unreferencedDataStoreCount,\n };\n }\n\n public aliases(): ReadonlyMap<string, string> {\n return this.aliasMap;\n }\n\n public processAttachMessage(message: ISequencedDocumentMessage, local: boolean) {\n const attachMessage = message.contents as InboundAttachMessage;\n\n this.dataStoresSinceLastGC.push(attachMessage.id);\n\n // The local object has already been attached\n if (local) {\n assert(this.pendingAttach.has(attachMessage.id),\n 0x15e /* \"Local object does not have matching attach message id\" */);\n this.contexts.get(attachMessage.id)?.emit(\"attached\");\n this.pendingAttach.delete(attachMessage.id);\n return;\n }\n\n // If a non-local operation then go and create the object, otherwise mark it as officially attached.\n if (this.alreadyProcessed(attachMessage.id)) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n const error = new DataCorruptionError(\n \"duplicateDataStoreCreatedWithExistingId\",\n {\n ...extractSafePropertiesFromMessage(message),\n dataStoreId: {\n value: attachMessage.id,\n tag: TelemetryDataTag.PackageData,\n },\n },\n );\n throw error;\n }\n\n const flatBlobs = new Map<string, ArrayBufferLike>();\n let snapshotTree: ISnapshotTree | undefined;\n if (attachMessage.snapshot) {\n snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);\n }\n\n // Include the type of attach message which is the pkg of the store to be\n // used by RemoteFluidDataStoreContext in case it is not in the snapshot.\n const pkg = [attachMessage.type];\n const remoteFluidDataStoreContext = new RemoteFluidDataStoreContext({\n id: attachMessage.id,\n snapshotTree,\n // New data stores begin with empty GC details since GC hasn't run on them yet.\n getBaseGCDetails: async () => { return {}; },\n runtime: this.runtime,\n storage: new BlobCacheStorageService(this.runtime.storage, flatBlobs),\n scope: this.runtime.scope,\n createSummarizerNodeFn: this.getCreateChildSummarizerNodeFn(\n attachMessage.id,\n {\n type: CreateSummarizerNodeSource.FromAttach,\n sequenceNumber: message.sequenceNumber,\n snapshot: attachMessage.snapshot ?? {\n entries: [createAttributesBlob(\n pkg,\n true /* isRootDataStore */,\n this.runtime.disableIsolatedChannels,\n )],\n },\n },\n ),\n writeGCDataAtRoot: this.writeGCDataAtRoot,\n disableIsolatedChannels: this.runtime.disableIsolatedChannels,\n pkg,\n });\n\n this.contexts.addBoundOrRemoted(remoteFluidDataStoreContext);\n }\n\n public processAliasMessage(\n message: ISequencedDocumentMessage,\n localOpMetadata: unknown,\n local: boolean,\n ): void {\n const aliasMessage = message.contents as IDataStoreAliasMessage;\n if (!isDataStoreAliasMessage(aliasMessage)) {\n throw new DataCorruptionError(\n \"malformedDataStoreAliasMessage\",\n {\n ...extractSafePropertiesFromMessage(message),\n },\n );\n }\n\n const resolve = localOpMetadata as PendingAliasResolve;\n const aliasResult = this.processAliasMessageCore(aliasMessage);\n if (local) {\n resolve(aliasResult);\n }\n }\n\n private processAliasMessageCore(aliasMessage: IDataStoreAliasMessage): boolean {\n if (this.alreadyProcessed(aliasMessage.alias)) {\n return false;\n }\n\n const currentContext = this.contexts.get(aliasMessage.internalId);\n if (currentContext === undefined) {\n this.logger.sendErrorEvent({\n eventName: \"AliasFluidDataStoreNotFound\",\n fluidDataStoreId: aliasMessage.internalId,\n });\n return false;\n }\n\n this.aliasMap.set(aliasMessage.alias, currentContext.id);\n currentContext.setRoot();\n return true;\n }\n\n private alreadyProcessed(id: string): boolean {\n return this.aliasMap.get(id) !== undefined || this.contexts.get(id) !== undefined;\n }\n\n public bindFluidDataStore(fluidDataStoreRuntime: IFluidDataStoreChannel): void {\n const id = fluidDataStoreRuntime.id;\n const localContext = this.contexts.getUnbound(id);\n assert(!!localContext, 0x15f /* \"Could not find unbound context to bind\" */);\n\n // If the container is detached, we don't need to send OP or add to pending attach because\n // we will summarize it while uploading the create new summary and make it known to other\n // clients.\n if (this.runtime.attachState !== AttachState.Detached) {\n localContext.emit(\"attaching\");\n const message = localContext.generateAttachMessage();\n\n this.pendingAttach.set(id, message);\n this.submitAttachFn(message);\n this.attachOpFiredForDataStore.add(id);\n }\n\n this.contexts.bind(fluidDataStoreRuntime.id);\n }\n\n public createDetachedDataStoreCore(\n pkg: Readonly<string[]>,\n isRoot: boolean,\n id = uuid()): IFluidDataStoreContextDetached\n {\n const context = new LocalDetachedFluidDataStoreContext({\n id,\n pkg,\n runtime: this.runtime,\n storage: this.runtime.storage,\n scope: this.runtime.scope,\n createSummarizerNodeFn: this.getCreateChildSummarizerNodeFn(\n id,\n { type: CreateSummarizerNodeSource.Local },\n ),\n bindChannelFn: (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n snapshotTree: undefined,\n isRootDataStore: isRoot,\n writeGCDataAtRoot: this.writeGCDataAtRoot,\n disableIsolatedChannels: this.runtime.disableIsolatedChannels,\n });\n this.contexts.addUnbound(context);\n return context;\n }\n\n public _createFluidDataStoreContext(pkg: string[], id: string, isRoot: boolean, props?: any) {\n const context = new LocalFluidDataStoreContext({\n id,\n pkg,\n runtime: this.runtime,\n storage: this.runtime.storage,\n scope: this.runtime.scope,\n createSummarizerNodeFn: this.getCreateChildSummarizerNodeFn(\n id,\n { type: CreateSummarizerNodeSource.Local },\n ),\n bindChannelFn: (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n snapshotTree: undefined,\n isRootDataStore: isRoot,\n writeGCDataAtRoot: this.writeGCDataAtRoot,\n disableIsolatedChannels: this.runtime.disableIsolatedChannels,\n createProps: props,\n });\n this.contexts.addUnbound(context);\n return context;\n }\n\n public get disposed() {return this.disposeOnce.evaluated;}\n public readonly dispose = () => this.disposeOnce.value;\n\n public resubmitDataStoreOp(content: any, localOpMetadata: unknown) {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x160 /* \"There should be a store context for the op\" */);\n context.reSubmit(envelope.contents, localOpMetadata);\n }\n\n public async applyStashedOp(content: any): Promise<unknown> {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x161 /* \"There should be a store context for the op\" */);\n return context.applyStashedOp(envelope.contents);\n }\n\n public async applyStashedAttachOp(message: IAttachMessage) {\n this.pendingAttach.set(message.id, message);\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n this.processAttachMessage({ contents: message } as ISequencedDocumentMessage, false);\n }\n\n public processFluidDataStoreOp(message: ISequencedDocumentMessage, local: boolean, localMessageMetadata: unknown) {\n const envelope = message.contents as IEnvelope;\n const transformed = { ...message, contents: envelope.contents };\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x162 /* \"There should be a store context for the op\" */);\n context.process(transformed, local, localMessageMetadata);\n\n // Notify that a data store changed. This is used to detect if a deleted data store is being used.\n this.dataStoreChanged(envelope.address);\n }\n\n public async getDataStore(id: string, wait: boolean): Promise<FluidDataStoreContext> {\n const internalId = this.aliasMap.get(id) ?? id;\n\n const context = await this.contexts.getBoundOrRemoted(internalId, wait);\n if (context === undefined) {\n // The requested data store does not exits. Throw a 404 response exception.\n const request = { url: id };\n throw responseToException(create404Response(request), request);\n }\n\n return context;\n }\n\n public processSignal(address: string, message: IInboundSignalMessage, local: boolean) {\n const context = this.contexts.get(address);\n if (!context) {\n // Attach message may not have been processed yet\n assert(!local, 0x163 /* \"Missing datastore for local signal\" */);\n this.logger.sendTelemetryEvent({\n eventName: \"SignalFluidDataStoreNotFound\",\n fluidDataStoreId: address,\n });\n return;\n }\n\n context.processSignal(message, local);\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n for (const [fluidDataStore, context] of this.contexts) {\n try {\n context.setConnectionState(connected, clientId);\n } catch (error) {\n this.logger.sendErrorEvent({\n eventName: \"SetConnectionStateError\",\n clientId,\n fluidDataStore,\n }, error);\n }\n }\n }\n\n public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {\n let eventName: \"attaching\" | \"attached\";\n if (attachState === AttachState.Attaching) {\n eventName = \"attaching\";\n } else {\n eventName = \"attached\";\n }\n for (const [,context] of this.contexts) {\n // Fire only for bounded stores.\n if (!this.contexts.isNotBound(context.id)) {\n context.emit(eventName);\n }\n }\n }\n\n public get size(): number {\n return this.contexts.size;\n }\n\n public async summarize(fullTree: boolean, trackState: boolean): Promise<ISummaryTreeWithStats> {\n const summaryBuilder = new SummaryTreeBuilder();\n\n // Iterate over each store and ask it to snapshot\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Summarizer works only with clients with no local changes!\n assert(context.attachState !== AttachState.Attaching,\n 0x165 /* \"Summarizer cannot work if client has local changes\" */);\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextSummary = await context.summarize(fullTree, trackState);\n summaryBuilder.addWithStats(contextId, contextSummary);\n }));\n\n return summaryBuilder.getSummaryTree();\n }\n\n public createSummary(): ISummaryTreeWithStats {\n const builder = new SummaryTreeBuilder();\n // Attaching graph of some stores can cause other stores to get bound too.\n // So keep taking summary until no new stores get bound.\n let notBoundContextsLength: number;\n do {\n const builderTree = builder.summary.tree;\n notBoundContextsLength = this.contexts.notBoundLength();\n // Iterate over each data store and ask it to snapshot\n Array.from(this.contexts)\n .filter(([key, _]) =>\n // Take summary of bounded data stores only, make sure we haven't summarized them already\n // and no attach op has been fired for that data store because for loader versions <= 0.24\n // we set attach state as \"attaching\" before taking createNew summary.\n !(this.contexts.isNotBound(key)\n || builderTree[key]\n || this.attachOpFiredForDataStore.has(key)),\n )\n .map(([key, value]) => {\n let dataStoreSummary: ISummarizeResult;\n if (value.isLoaded) {\n const snapshot = value.generateAttachMessage().snapshot;\n dataStoreSummary = convertToSummaryTree(snapshot, true);\n } else {\n // If this data store is not yet loaded, then there should be no changes in the snapshot from\n // which it was created as it is detached container. So just use the previous snapshot.\n assert(!!this.baseSnapshot,\n 0x166 /* \"BaseSnapshot should be there as detached container loaded from snapshot\" */);\n dataStoreSummary = convertSnapshotTreeToSummaryTree(this.baseSnapshot.trees[key]);\n }\n builder.addWithStats(key, dataStoreSummary);\n });\n } while (notBoundContextsLength !== this.contexts.notBoundLength());\n\n return builder.getSummaryTree();\n }\n\n /**\n * Before GC runs, called by the garbage collector to update any pending GC state.\n * The garbage collector needs to know all outbound references that are added. Since root data stores are not\n * explicitly marked as referenced, notify GC of new root data stores that were added since the last GC run.\n */\n public async updateStateBeforeGC(): Promise<void> {\n for (const id of this.dataStoresSinceLastGC) {\n const context = this.contexts.get(id);\n assert(context !== undefined, 0x2b6 /* `Missing data store context with id ${id}` */);\n if (await context.isRoot()) {\n // A root data store is basically a reference from the container runtime to the data store.\n const handle = new FluidObjectHandle(context, id, this.runtime.IFluidHandleContext);\n this.runtime.addedGCOutboundReference(this.containerRuntimeHandle, handle);\n }\n }\n this.dataStoresSinceLastGC = [];\n }\n\n /**\n * Generates data used for garbage collection. It does the following:\n * 1. Calls into each child data store context to get its GC data.\n * 2. Prefixes the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be\n * identified as belonging to the child.\n * 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent\n * the GC data of this channel.\n * @param fullGC - true to bypass optimizations and force full generation of GC data.\n */\n public async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n const builder = new GCDataBuilder();\n // Iterate over each store and get their GC data.\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Get GC data only for attached contexts. Detached contexts are not connected in the GC reference\n // graph so any references they might have won't be connected as well.\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextGCData = await context.getGCData(fullGC);\n // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.\n // This also gradually builds the id of each node to be a path from the root.\n builder.prefixAndAddNodes(contextId, contextGCData.gcNodes);\n }));\n\n // Get the outbound routes and add a GC node for this channel.\n builder.addNode(\"/\", await this.getOutboundRoutes());\n return builder.getGCData();\n }\n\n /**\n * After GC has run, called to notify this Container's data stores of routes that are used in it.\n * @param usedRoutes - The routes that are used in all data stores in this Container.\n * @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes\n * unreferenced as part of this GC run, this should be used to update the time when it happens.\n * @returns the statistics of the used state of the data stores.\n */\n public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): IUsedStateStats {\n // Get a map of data store ids to routes used in it.\n const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);\n\n // Verify that the used routes are correct.\n for (const [id] of usedDataStoreRoutes) {\n assert(this.contexts.has(id), 0x167 /* \"Used route does not belong to any known data store\" */);\n }\n\n // Update the used routes in each data store. Used routes is empty for unused data stores.\n for (const [contextId, context] of this.contexts) {\n context.updateUsedRoutes(usedDataStoreRoutes.get(contextId) ?? [], gcTimestamp);\n }\n\n // Return the number of data stores that are unused.\n const dataStoreCount = this.contexts.size;\n return {\n totalNodeCount: dataStoreCount,\n unusedNodeCount: dataStoreCount - usedDataStoreRoutes.size,\n };\n }\n\n /**\n * When running GC in test mode, this is called to delete objects whose routes are unused. This enables testing\n * scenarios with accessing deleted content.\n * @param unusedRoutes - The routes that are unused in all data stores in this Container.\n */\n public deleteUnusedRoutes(unusedRoutes: string[]) {\n for (const route of unusedRoutes) {\n const dataStoreId = route.split(\"/\")[1];\n // Delete the contexts of unused data stores.\n this.contexts.delete(dataStoreId);\n // Delete the summarizer node of the unused data stores.\n this.deleteChildSummarizerNodeFn(dataStoreId);\n }\n }\n\n /**\n * Returns the outbound routes of this channel. Only root data stores are considered referenced and their paths are\n * part of outbound routes.\n */\n private async getOutboundRoutes(): Promise<string[]> {\n const outboundRoutes: string[] = [];\n for (const [contextId, context] of this.contexts) {\n const isRootDataStore = await context.isRoot();\n if (isRootDataStore) {\n outboundRoutes.push(`/${contextId}`);\n }\n }\n return outboundRoutes;\n }\n}\n\nexport function getSummaryForDatastores(\n snapshot: ISnapshotTree | undefined,\n metadata?: IContainerRuntimeMetadata,\n): ISnapshotTree | undefined {\n if (!snapshot) {\n return undefined;\n }\n\n if (rootHasIsolatedChannels(metadata)) {\n const datastoresSnapshot = snapshot.trees[channelsTreeName];\n assert(!!datastoresSnapshot, 0x168 /* `expected ${channelsTreeName} tree in snapshot` */);\n return datastoresSnapshot;\n } else {\n // back-compat: strip out all non-datastore paths before giving to DataStores object.\n const datastoresTrees: ISnapshotTree[\"trees\"] = {};\n for (const [key, value] of Object.entries(snapshot.trees)) {\n if (!nonDataStorePaths.includes(key)) {\n datastoresTrees[key] = value;\n }\n }\n return {\n ...snapshot,\n trees: datastoresTrees,\n };\n }\n}\n"]}
|
|
@@ -44,8 +44,8 @@ export interface IGarbageCollector {
|
|
|
44
44
|
* 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.
|
|
45
45
|
*/
|
|
46
46
|
readonly gcSummaryFeatureVersion: number;
|
|
47
|
-
/** Tells whether the GC
|
|
48
|
-
readonly
|
|
47
|
+
/** Tells whether the GC state in summary needs to be reset in the next summary. */
|
|
48
|
+
readonly summaryStateNeedsReset: boolean;
|
|
49
49
|
/** Tells whether GC data should be written to the root of the summary tree. */
|
|
50
50
|
readonly writeDataAtRoot: boolean;
|
|
51
51
|
/** Run garbage collection and update the reference / used state of the system. */
|
|
@@ -63,9 +63,9 @@ export interface IGarbageCollector {
|
|
|
63
63
|
latestSummaryStateRefreshed(result: RefreshSummaryResult, readAndParseBlob: ReadAndParseBlob): Promise<void>;
|
|
64
64
|
/** Called when a node is changed. Used to detect and log when an inactive node is changed. */
|
|
65
65
|
nodeChanged(id: string): void;
|
|
66
|
-
dispose(): void;
|
|
67
66
|
/** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
|
|
68
67
|
addedOutboundReference(fromNodeId: string, toNodeId: string): void;
|
|
68
|
+
dispose(): void;
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
71
|
* The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains
|
|
@@ -95,9 +95,14 @@ export declare class GarbageCollector implements IGarbageCollector {
|
|
|
95
95
|
*/
|
|
96
96
|
get gcSummaryFeatureVersion(): number;
|
|
97
97
|
/**
|
|
98
|
-
* Tells whether the GC
|
|
98
|
+
* Tells whether the GC state needs to be reset in the next summary. We need to do this if:
|
|
99
|
+
* 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
|
|
100
|
+
* 2. GC was disabled and is now enabled. The GC state needs to be regenerated and added to summary.
|
|
101
|
+
* 3. The GC version in the latest summary is different from the current GC version. This can happen if:
|
|
102
|
+
* 3.1. The summary this client loaded with has data from a different GC version.
|
|
103
|
+
* 3.2. This client's latest summary was updated from a snapshot that has a different GC version.
|
|
99
104
|
*/
|
|
100
|
-
get
|
|
105
|
+
get summaryStateNeedsReset(): boolean;
|
|
101
106
|
/**
|
|
102
107
|
* Tracks if GC is enabled for this document. This is specified during document creation and doesn't change
|
|
103
108
|
* throughout its lifetime.
|
|
@@ -107,13 +112,21 @@ export declare class GarbageCollector implements IGarbageCollector {
|
|
|
107
112
|
private readonly testMode;
|
|
108
113
|
private readonly mc;
|
|
109
114
|
/**
|
|
110
|
-
* Tells whether the GC data should be written to the root of the summary tree.
|
|
111
|
-
* 1. If `writeDataAtRoot` GC option is enabled.
|
|
112
|
-
* 2. If the base summary has the GC data written at the root. This is to support forward compatibility where when
|
|
113
|
-
* we start writing the GC data at root, older versions can detect that and write at root too.
|
|
115
|
+
* Tells whether the GC data should be written to the root of the summary tree.
|
|
114
116
|
*/
|
|
115
117
|
private _writeDataAtRoot;
|
|
116
118
|
get writeDataAtRoot(): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Tells whether the initial GC state needs to be reset. This can happen under 2 conditions:
|
|
121
|
+
* 1. The base snapshot contains GC state but GC is disabled. This will happen the first time GC is disabled after
|
|
122
|
+
* it was enabled before. GC state needs to be removed from summary and all nodes should be marked referenced.
|
|
123
|
+
* 2. The base snapshot does not have GC state but GC is enabled. This will happen the very first time GC runs on
|
|
124
|
+
* a document and the first time GC is enabled after is was disabled before.
|
|
125
|
+
*
|
|
126
|
+
* Note that the state needs reset only for the very first time summary is generated by this client. After that, the
|
|
127
|
+
* state will be up-to-date and this flag will be reset.
|
|
128
|
+
*/
|
|
129
|
+
private initialStateNeedsReset;
|
|
117
130
|
private readonly currentGCVersion;
|
|
118
131
|
private latestSummaryGCVersion;
|
|
119
132
|
private gcDataFromLastRun;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../src/garbageCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAUhF,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAEH,sBAAsB,EAEtB,6BAA6B,EAC7B,qBAAqB,EACxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EAEvB,MAAM,+BAA+B,CAAC;AAQvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAGH,yBAAyB,EAI5B,MAAM,iBAAiB,CAAC;AAMzB,eAAO,MAAM,SAAS,OAAO,CAAC;AAE9B,eAAO,MAAM,YAAY,SAAS,CAAC;AAanC,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC7B;AAED,qFAAqF;AACrF,MAAM,WAAW,yBAAyB;IACtC,mFAAmF;IACnF,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,0DAA0D;IAC1D,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC7D,oFAAoF;IACpF,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;CACjF;AAED,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IACpD;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,mFAAmF;IACnF,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,kFAAkF;IAClF,cAAc,CACV,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC9F,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrB,+DAA+D;IAC/D,SAAS,IAAI,qBAAqB,GAAG,SAAS,CAAC;IAC/C,iFAAiF;IACjF,yBAAyB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC,CAAC;IACjF,uEAAuE;IACvE,2BAA2B,CAAC,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7G,8FAA8F;IAC9F,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iHAAiH;IACjH,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACnE,OAAO,IAAI,IAAI,CAAC;CACnB;AAqDD;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;IA+GlD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;WApHd,MAAM,CAChB,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,iBAAiB,EAC5B,kBAAkB,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI,EACpD,qBAAqB,EAAE,MAAM,MAAM,EACnC,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,uBAAuB,KAAK,IAAI,EAClD,YAAY,EAAE,aAAa,GAAG,SAAS,EACvC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,yBAAyB,GACrC,iBAAiB;IAepB;;OAEG;IACH,SAAgB,WAAW,EAAE,OAAO,CAAC;IAErC;;OAEG;IACH,SAAgB,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3D;;;;OAIG;IACH,IAAW,uBAAuB,IAAI,MAAM,CAE3C;IAED;;;;;;;OAOG;IACH,IAAW,sBAAsB,IAAI,OAAO,CAG3C;IAED;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,IAAW,eAAe,IAAI,OAAO,CAEnC;IAEF;;;;;;;;;MASE;IACF,OAAO,CAAC,sBAAsB,CAAkB;IAGhD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAa;IAE9C,OAAO,CAAC,sBAAsB,CAAY;IAG1C,OAAO,CAAC,iBAAiB,CAAqC;IAG9D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoC;IAG3E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAgB;IAErD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsD;IAE1F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoD;IAE3F,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAE3D,SAAS,aACY,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,iBAAiB;IAC7C,yFAAyF;IACxE,kBAAkB,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI;IACrE,sFAAsF;IACrE,qBAAqB,EAAE,MAAM,MAAM,EACnC,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,uBAAuB,KAAK,IAAI,EACnE,YAAY,EAAE,aAAa,GAAG,SAAS,EACvC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,yBAAyB;IA+LxC;;;OAGG;IACU,cAAc,CACvB,OAAO,EAAE;QACL,0CAA0C;QAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAC1B,sDAAsD;QACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,oCAAoC;QACpC,MAAM,CAAC,EAAE,OAAO,CAAC;KACpB,GACF,OAAO,CAAC,QAAQ,CAAC;IA2DpB;;;;OAIG;IACI,SAAS,IAAI,qBAAqB,GAAG,SAAS;IAkBrD;;;OAGG;IACU,yBAAyB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IAI7F;;;OAGG;IACU,2BAA2B,CACpC,MAAM,EAAE,oBAAoB,EAC5B,gBAAgB,EAAE,gBAAgB,GACnC,OAAO,CAAC,IAAI,CAAC;IAoBhB;;OAEG;IACI,WAAW,CAAC,EAAE,EAAE,MAAM;IAYtB,OAAO,IAAI,IAAI;IAOtB;;;;;;OAMG;IACI,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAMlE;;OAEG;YACW,kCAAkC;IAQhD;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAyC1B;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAkDjC;;;;;;;OAOG;IACH,OAAO,CAAC,4BAA4B;CA6CvC"}
|
package/lib/garbageCollection.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { assert, LazyPromise, Timer } from "@fluidframework/common-utils";
|
|
6
|
+
import { ClientSessionExpiredError } from "@fluidframework/container-utils";
|
|
6
7
|
import { cloneGCData, concatGarbageCollectionStates, concatGarbageCollectionData, runGarbageCollection, unpackChildNodesGCDetails, } from "@fluidframework/garbage-collector";
|
|
7
8
|
import { gcBlobKey, } from "@fluidframework/runtime-definitions";
|
|
8
9
|
import { SummaryTreeBuilder, } from "@fluidframework/runtime-utils";
|
|
@@ -15,12 +16,14 @@ const GCVersion = 1;
|
|
|
15
16
|
export const gcTreeKey = "gc";
|
|
16
17
|
// They prefix for GC blobs in the GC tree in summary.
|
|
17
18
|
export const gcBlobPrefix = "__gc";
|
|
18
|
-
//
|
|
19
|
+
// Feature gate key to turn GC on / off.
|
|
19
20
|
const runGCKey = "Fluid.GarbageCollection.RunGC";
|
|
20
|
-
//
|
|
21
|
+
// Feature gate key to turn GC test mode on / off.
|
|
21
22
|
const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
|
|
22
|
-
//
|
|
23
|
+
// Feature gate key to turn GC sweep on / off.
|
|
23
24
|
const runSweepKey = "Fluid.GarbageCollection.RunSweep";
|
|
25
|
+
// Feature gate key to write GC data at the root of the summary tree.
|
|
26
|
+
const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
|
|
24
27
|
const defaultDeleteTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
25
28
|
/**
|
|
26
29
|
* Helper class that tracks the state of an unreferenced node such as the time it was unreferenced. It also sets
|
|
@@ -72,19 +75,27 @@ export class GarbageCollector {
|
|
|
72
75
|
deleteUnusedRoutes,
|
|
73
76
|
/** Returns the current timestamp to be assigned to nodes that become unreferenced. */
|
|
74
77
|
getCurrentTimestampMs, closeFn, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
|
|
75
|
-
var _a, _b, _c, _d;
|
|
78
|
+
var _a, _b, _c, _d, _e;
|
|
76
79
|
this.provider = provider;
|
|
77
80
|
this.gcOptions = gcOptions;
|
|
78
81
|
this.deleteUnusedRoutes = deleteUnusedRoutes;
|
|
79
82
|
this.getCurrentTimestampMs = getCurrentTimestampMs;
|
|
80
83
|
this.closeFn = closeFn;
|
|
81
84
|
/**
|
|
82
|
-
* Tells whether the GC data should be written to the root of the summary tree.
|
|
83
|
-
* 1. If `writeDataAtRoot` GC option is enabled.
|
|
84
|
-
* 2. If the base summary has the GC data written at the root. This is to support forward compatibility where when
|
|
85
|
-
* we start writing the GC data at root, older versions can detect that and write at root too.
|
|
85
|
+
* Tells whether the GC data should be written to the root of the summary tree.
|
|
86
86
|
*/
|
|
87
87
|
this._writeDataAtRoot = false;
|
|
88
|
+
/**
|
|
89
|
+
* Tells whether the initial GC state needs to be reset. This can happen under 2 conditions:
|
|
90
|
+
* 1. The base snapshot contains GC state but GC is disabled. This will happen the first time GC is disabled after
|
|
91
|
+
* it was enabled before. GC state needs to be removed from summary and all nodes should be marked referenced.
|
|
92
|
+
* 2. The base snapshot does not have GC state but GC is enabled. This will happen the very first time GC runs on
|
|
93
|
+
* a document and the first time GC is enabled after is was disabled before.
|
|
94
|
+
*
|
|
95
|
+
* Note that the state needs reset only for the very first time summary is generated by this client. After that, the
|
|
96
|
+
* state will be up-to-date and this flag will be reset.
|
|
97
|
+
*/
|
|
98
|
+
this.initialStateNeedsReset = false;
|
|
88
99
|
// The current GC version that this container is running.
|
|
89
100
|
this.currentGCVersion = GCVersion;
|
|
90
101
|
// Keeps a list of references (edges in the GC graph) between GC runs. Each entry has a node id and a list of
|
|
@@ -112,15 +123,8 @@ export class GarbageCollector {
|
|
|
112
123
|
}
|
|
113
124
|
// If session expiry is enabled, we need to close the container when the timeout expires
|
|
114
125
|
if (this.sessionExpiryTimeoutMs !== undefined) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// new ClientSessionExpiredError(`Client expired, it has lasted ${this.sessionExpiryTimeoutMs} ms.`,
|
|
118
|
-
// this.sessionExpiryTimeoutMs)),
|
|
119
|
-
// this.sessionExpiryTimeoutMs);
|
|
120
|
-
this.sessionExpiryTimer = setTimeout(() => this.closeFn({
|
|
121
|
-
errorType: "clientSessionExpiredError",
|
|
122
|
-
message: `The client has reached the expiry time of ${this.sessionExpiryTimeoutMs} ms.`,
|
|
123
|
-
}), this.sessionExpiryTimeoutMs);
|
|
126
|
+
const expiryMs = this.sessionExpiryTimeoutMs;
|
|
127
|
+
this.sessionExpiryTimer = setTimeout(() => this.closeFn(new ClientSessionExpiredError(`Client session expired.`, expiryMs)), expiryMs);
|
|
124
128
|
}
|
|
125
129
|
// For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
|
|
126
130
|
// latest tracked GC version. For new documents, we will be writing the first summary with the current version.
|
|
@@ -138,9 +142,18 @@ export class GarbageCollector {
|
|
|
138
142
|
&& this.sessionExpiryTimer !== undefined;
|
|
139
143
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
140
144
|
this.testMode = (_d = this.mc.config.getBoolean(gcTestModeKey)) !== null && _d !== void 0 ? _d : gcOptions.runGCInTestMode === true;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Enable resetting initial state once the following issue is resolved:
|
|
147
|
+
* https://github.com/microsoft/FluidFramework/issues/8878.
|
|
148
|
+
* Currently, the GC tree is not written at root, so we don't know if the base snapshot contains GC tree or not.
|
|
149
|
+
*/
|
|
150
|
+
// The GC state needs to be reset if the base snapshot contains GC tree and GC is disabled or it doesn't contain
|
|
151
|
+
// GC tree and GC is enabled.
|
|
152
|
+
// const gcTreePresent = baseSnapshot?.trees[gcTreeKey] !== undefined;
|
|
153
|
+
// this.initialStateNeedsReset = gcTreePresent ? !this.shouldRunGC : this.shouldRunGC;
|
|
154
|
+
// If `writeDataAtRoot` setting is true, write the GC data into the root of the summary tree. We do this so that
|
|
155
|
+
// the roll out can be staged. Once its rolled out everywhere, we will start writing at root by default.
|
|
156
|
+
this._writeDataAtRoot = (_e = this.mc.config.getBoolean(writeAtRootKey)) !== null && _e !== void 0 ? _e : this.gcOptions.writeDataAtRoot === true;
|
|
144
157
|
// Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do
|
|
145
158
|
// this once since it involves fetching blobs from storage which is expensive.
|
|
146
159
|
const baseSummaryStateP = new LazyPromise(async () => {
|
|
@@ -151,7 +164,7 @@ export class GarbageCollector {
|
|
|
151
164
|
// For newer documents, GC data should be present in the GC tree in the root of the snapshot.
|
|
152
165
|
const gcSnapshotTree = baseSnapshot.trees[gcTreeKey];
|
|
153
166
|
if (gcSnapshotTree !== undefined) {
|
|
154
|
-
//
|
|
167
|
+
// If the GC tree is written at root, we should also do the same.
|
|
155
168
|
this._writeDataAtRoot = true;
|
|
156
169
|
return getGCStateFromSnapshot(gcSnapshotTree, readAndParseBlob);
|
|
157
170
|
}
|
|
@@ -253,13 +266,16 @@ export class GarbageCollector {
|
|
|
253
266
|
return this.gcEnabled ? this.currentGCVersion : 0;
|
|
254
267
|
}
|
|
255
268
|
/**
|
|
256
|
-
* Tells whether the GC
|
|
269
|
+
* Tells whether the GC state needs to be reset in the next summary. We need to do this if:
|
|
270
|
+
* 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
|
|
271
|
+
* 2. GC was disabled and is now enabled. The GC state needs to be regenerated and added to summary.
|
|
272
|
+
* 3. The GC version in the latest summary is different from the current GC version. This can happen if:
|
|
273
|
+
* 3.1. The summary this client loaded with has data from a different GC version.
|
|
274
|
+
* 3.2. This client's latest summary was updated from a snapshot that has a different GC version.
|
|
257
275
|
*/
|
|
258
|
-
get
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// 2. This client's latest summary was updated from a snapshot that has a different GC version.
|
|
262
|
-
return this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion;
|
|
276
|
+
get summaryStateNeedsReset() {
|
|
277
|
+
return this.initialStateNeedsReset ||
|
|
278
|
+
(this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion);
|
|
263
279
|
}
|
|
264
280
|
get writeDataAtRoot() {
|
|
265
281
|
return this._writeDataAtRoot;
|
|
@@ -269,7 +285,7 @@ export class GarbageCollector {
|
|
|
269
285
|
* @returns the number of data stores that have been marked as unreferenced.
|
|
270
286
|
*/
|
|
271
287
|
async collectGarbage(options) {
|
|
272
|
-
const { logger = this.mc.logger, runSweep = this.shouldRunSweep, fullGC = this.gcOptions.runFullGC === true || this.
|
|
288
|
+
const { logger = this.mc.logger, runSweep = this.shouldRunSweep, fullGC = this.gcOptions.runFullGC === true || this.summaryStateNeedsReset, } = options;
|
|
273
289
|
return PerformanceEvent.timedExecAsync(logger, { eventName: "GarbageCollection" }, async (event) => {
|
|
274
290
|
await this.initializeBaseStateP;
|
|
275
291
|
// Let the runtime update its pending state before GC runs.
|
|
@@ -333,6 +349,9 @@ export class GarbageCollector {
|
|
|
333
349
|
* latest summary tracked.
|
|
334
350
|
*/
|
|
335
351
|
async latestSummaryStateRefreshed(result, readAndParseBlob) {
|
|
352
|
+
// After a summary is successfully submitted and ack'd by this client, the GC state should have been reset in
|
|
353
|
+
// the summary and doesn't need to be reset anymore.
|
|
354
|
+
this.initialStateNeedsReset = false;
|
|
336
355
|
if (!this.shouldRunGC || !result.latestSummaryUpdated) {
|
|
337
356
|
return;
|
|
338
357
|
}
|
|
@@ -515,12 +534,16 @@ export class GarbageCollector {
|
|
|
515
534
|
// Validate references for data stores only whose routes are of the format "/dataStoreId". Currently, layers
|
|
516
535
|
// below data stores don't have GC implemented so there is no guarantee their references will be notified.
|
|
517
536
|
if (route.split("/").length === 2 && !explicitReferences.includes(route)) {
|
|
537
|
+
/**
|
|
538
|
+
* The following log will be enabled once this issue is resolved:
|
|
539
|
+
* https://github.com/microsoft/FluidFramework/issues/8878.
|
|
540
|
+
*/
|
|
518
541
|
// We should ideally throw a data corruption error here. However, send an error for now until we have
|
|
519
542
|
// implemented sweep and have reasonable confidence in the sweep process.
|
|
520
|
-
this.mc.logger.sendErrorEvent({
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
});
|
|
543
|
+
// this.mc.logger.sendErrorEvent({
|
|
544
|
+
// eventName: "gcUnknownOutboundRoute",
|
|
545
|
+
// route,
|
|
546
|
+
// });
|
|
524
547
|
}
|
|
525
548
|
});
|
|
526
549
|
}
|