@fluidframework/datastore 0.58.3000-61081 → 0.59.1000-61898
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/dataStoreRuntime.d.ts +17 -5
- package/dist/dataStoreRuntime.d.ts.map +1 -1
- package/dist/dataStoreRuntime.js +106 -57
- package/dist/dataStoreRuntime.js.map +1 -1
- package/dist/fluidHandle.d.ts +8 -4
- package/dist/fluidHandle.d.ts.map +1 -1
- package/dist/fluidHandle.js +28 -20
- package/dist/fluidHandle.js.map +1 -1
- package/dist/localChannelContext.d.ts +2 -2
- package/dist/localChannelContext.d.ts.map +1 -1
- package/dist/localChannelContext.js +9 -9
- package/dist/localChannelContext.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/dataStoreRuntime.d.ts +17 -5
- package/lib/dataStoreRuntime.d.ts.map +1 -1
- package/lib/dataStoreRuntime.js +107 -58
- package/lib/dataStoreRuntime.js.map +1 -1
- package/lib/fluidHandle.d.ts +8 -4
- package/lib/fluidHandle.d.ts.map +1 -1
- package/lib/fluidHandle.js +28 -20
- package/lib/fluidHandle.js.map +1 -1
- package/lib/localChannelContext.d.ts +2 -2
- package/lib/localChannelContext.d.ts.map +1 -1
- package/lib/localChannelContext.js +9 -9
- package/lib/localChannelContext.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +25 -19
- package/src/dataStoreRuntime.ts +123 -64
- package/src/fluidHandle.ts +31 -24
- package/src/localChannelContext.ts +9 -9
- package/src/packageVersion.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localChannelContext.js","sourceRoot":"","sources":["../src/localChannelContext.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\n// eslint-disable-next-line import/no-internal-modules\nimport cloneDeep from \"lodash/cloneDeep\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n IChannel,\n IFluidDataStoreRuntime,\n IChannelFactory,\n IChannelAttributes,\n} from \"@fluidframework/datastore-definitions\";\nimport {\n IFluidDataStoreContext,\n IGarbageCollectionData,\n ISummarizeResult,\n} from \"@fluidframework/runtime-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport { DataProcessingError } from \"@fluidframework/container-utils\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport {\n createServiceEndpoints,\n IChannelContext,\n summarizeChannel,\n summarizeChannelAsync,\n} from \"./channelContext\";\nimport { ChannelDeltaConnection } from \"./channelDeltaConnection\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime\";\nimport { ChannelStorageService } from \"./channelStorageService\";\n\n/**\n * Channel context for a locally created channel\n */\nexport abstract class LocalChannelContextBase implements IChannelContext {\n public channel: IChannel | undefined;\n private attached = false;\n protected readonly pending: ISequencedDocumentMessage[] = [];\n protected factory: IChannelFactory | undefined;\n constructor(\n protected readonly id: string,\n protected readonly registry: ISharedObjectRegistry,\n protected readonly runtime: IFluidDataStoreRuntime,\n private readonly servicesGetter: () => Lazy<{\n readonly deltaConnection: ChannelDeltaConnection,\n readonly objectStorage: ChannelStorageService,\n }>,\n ) {\n }\n\n public async getChannel(): Promise<IChannel> {\n assert(this.channel !== undefined, 0x207 /* \"Channel should be defined\" */);\n return this.channel;\n }\n\n public get isLoaded(): boolean {\n return this.channel !== undefined;\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n // Connection events are ignored if the data store is not yet attached or loaded\n if (this.attached && this.isLoaded) {\n this.servicesGetter().value.deltaConnection.setConnectionState(connected);\n }\n }\n\n public processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void {\n assert(this.attached, 0x188 /* \"Local channel must be attached when processing op\" */);\n\n // A local channel may not be loaded in case where we rehydrate the container from a snapshot because of\n // delay loading. So after the container is attached and some other client joins which start generating\n // ops for this channel. So not loaded local channel can still receive ops and we store them to process later.\n if (this.isLoaded) {\n this.servicesGetter().value.deltaConnection.process(message, local, localOpMetadata);\n } else {\n assert(local === false,\n 0x189 /* \"Should always be remote because a local dds shouldn't generate ops before loading\" */);\n this.pending.push(message);\n }\n }\n\n public reSubmit(content: any, localOpMetadata: unknown) {\n assert(this.isLoaded, 0x18a /* \"Channel should be loaded to resubmit ops\" */);\n assert(this.attached, 0x18b /* \"Local channel must be attached when resubmitting op\" */);\n this.servicesGetter().value.deltaConnection.reSubmit(content, localOpMetadata);\n }\n\n public applyStashedOp() {\n throw new Error(\"no stashed ops on local channel\");\n }\n\n /**\n * Returns a summary at the current sequence number.\n * @param fullTree - true to bypass optimizations and force a full summary tree\n * @param trackState - This tells whether we should track state from this summary.\n */\n public async summarize(fullTree: boolean = false, trackState: boolean = false): Promise<ISummarizeResult> {\n assert(this.isLoaded && this.channel !== undefined, 0x18c /* \"Channel should be loaded to summarize\" */);\n return summarizeChannelAsync(this.channel, fullTree, trackState);\n }\n\n public getAttachSummary(): ISummarizeResult {\n assert(this.isLoaded && this.channel !== undefined, 0x18d /* \"Channel should be loaded to take snapshot\" */);\n return summarizeChannel(this.channel, true /* fullTree */, false /* trackState */);\n }\n\n public markAttached(): void {\n if (this.attached) {\n throw new Error(\"Channel is already attached\");\n }\n\n if (this.isLoaded) {\n assert(!!this.channel, 0x192 /* \"Channel should be there if loaded!!\" */);\n this.channel.connect(this.servicesGetter().value);\n }\n this.attached = true;\n }\n\n /**\n * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.\n * Each node has a set of outbound routes to other GC nodes in the document. This should be called only after\n * the context has loaded.\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 assert(this.isLoaded && this.channel !== undefined, 0x193 /* \"Channel should be loaded to run GC\" */);\n return this.channel.getGCData(fullGC);\n }\n\n public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number) {\n /**\n * Currently, DDSs are always considered referenced and are not garbage collected.\n * Once we have GC at DDS level, this channel context's used routes will be updated as per the passed\n * value. See - https://github.com/microsoft/FluidFramework/issues/4611\n */\n }\n}\n\nexport class RehydratedLocalChannelContext extends LocalChannelContextBase {\n private readonly services: Lazy<{\n readonly deltaConnection: ChannelDeltaConnection,\n readonly objectStorage: ChannelStorageService,\n }>;\n\n private readonly dirtyFn: () => void;\n\n constructor(\n id: string,\n registry: ISharedObjectRegistry,\n runtime: IFluidDataStoreRuntime,\n dataStoreContext: IFluidDataStoreContext,\n storageService: IDocumentStorageService,\n logger: ITelemetryLogger,\n submitFn: (content: any, localOpMetadata: unknown) => void,\n dirtyFn: (address: string) => void,\n addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n private readonly snapshotTree: ISnapshotTree,\n ) {\n super(id, registry, runtime, () => this.services);\n const blobMap: Map<string, ArrayBufferLike> = new Map<string, ArrayBufferLike>();\n const clonedSnapshotTree = cloneDeep(this.snapshotTree);\n // 0.47 back-compat Need to sanitize if snapshotTree.blobs still contains blob contents too.\n // This is for older snapshot which is generated by loader <=0.47 version which still contains\n // the contents within blobs. After a couple of revisions we can remove it.\n if (this.isSnapshotInOldFormatAndCollectBlobs(clonedSnapshotTree, blobMap)) {\n this.sanitizeSnapshot(clonedSnapshotTree);\n }\n\n this.services = new Lazy(() => {\n return createServiceEndpoints(\n this.id,\n dataStoreContext.connected,\n submitFn,\n this.dirtyFn,\n addedGCOutboundReferenceFn,\n storageService,\n logger,\n clonedSnapshotTree,\n blobMap,\n );\n });\n this.dirtyFn = () => { dirtyFn(id); };\n }\n\n public async getChannel(): Promise<IChannel> {\n if (this.channel === undefined) {\n this.channel = await this.loadChannel()\n .catch((err) => {\n throw DataProcessingError.wrapIfUnrecognized(\n err, \"rehydratedLocalChannelContextFailedToLoadChannel\", undefined);\n });\n }\n return this.channel;\n }\n\n private async loadChannel(): Promise<IChannel> {\n assert(!this.isLoaded, 0x18e /* \"Channel must not already be loaded when loading\" */);\n assert(await this.services.value.objectStorage.contains(\".attributes\"),\n 0x190 /* \".attributes blob should be present\" */);\n const attributes = await readAndParse<IChannelAttributes>(\n this.services.value.objectStorage,\n \".attributes\");\n\n assert(this.factory === undefined, 0x208 /* \"Factory should be undefined before loading\" */);\n this.factory = this.registry.get(attributes.type);\n if (this.factory === undefined) {\n throw new Error(`Channel Factory ${attributes.type} not registered`);\n }\n // Services will be assigned during this load.\n const channel = await this.factory.load(\n this.runtime,\n this.id,\n this.services.value,\n attributes);\n\n // Commit changes.\n this.channel = channel;\n\n // Send all pending messages to the channel\n for (const message of this.pending) {\n this.services.value.deltaConnection.process(message, false, undefined /* localOpMetadata */);\n }\n return this.channel;\n }\n\n private isSnapshotInOldFormatAndCollectBlobs(\n snapshotTree: ISnapshotTree,\n blobMap: Map<string, ArrayBufferLike>,\n ): boolean {\n let sanitize = false;\n const blobsContents: {[path: string]: ArrayBufferLike} = (snapshotTree as any).blobsContents;\n Object.entries(blobsContents).forEach(([key, value]) => {\n blobMap.set(key, value);\n if (snapshotTree.blobs[key] !== undefined) {\n sanitize = true;\n }\n });\n for (const value of Object.values(snapshotTree.trees)) {\n sanitize = sanitize || this.isSnapshotInOldFormatAndCollectBlobs(value, blobMap);\n }\n return sanitize;\n }\n\n private sanitizeSnapshot(snapshotTree: ISnapshotTree) {\n const blobMapInitial = new Map(Object.entries(snapshotTree.blobs));\n for (const [blobName, blobId] of blobMapInitial.entries()) {\n const blobValue = blobMapInitial.get(blobId);\n if (blobValue === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete snapshotTree.blobs[blobName];\n }\n }\n for (const value of Object.values(snapshotTree.trees)) {\n this.sanitizeSnapshot(value);\n }\n }\n}\n\nexport class LocalChannelContext extends LocalChannelContextBase {\n private readonly services: Lazy<{\n readonly deltaConnection: ChannelDeltaConnection,\n readonly objectStorage: ChannelStorageService,\n }>;\n private readonly dirtyFn: () => void;\n constructor(\n id: string,\n registry: ISharedObjectRegistry,\n type: string,\n runtime: IFluidDataStoreRuntime,\n dataStoreContext: IFluidDataStoreContext,\n storageService: IDocumentStorageService,\n logger: ITelemetryLogger,\n submitFn: (content: any, localOpMetadata: unknown) => void,\n dirtyFn: (address: string) => void,\n addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n ) {\n super(id, registry, runtime, () => this.services);\n assert(type !== undefined, 0x209 /* \"Factory Type should be defined\" */);\n this.factory = registry.get(type);\n if (this.factory === undefined) {\n throw new Error(`Channel Factory ${type} not registered`);\n }\n this.channel = this.factory.create(runtime, id);\n this.services = new Lazy(() => {\n return createServiceEndpoints(\n this.id,\n dataStoreContext.connected,\n submitFn,\n this.dirtyFn,\n addedGCOutboundReferenceFn,\n storageService,\n logger,\n );\n });\n this.dirtyFn = () => { dirtyFn(id); };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"localChannelContext.js","sourceRoot":"","sources":["../src/localChannelContext.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\n// eslint-disable-next-line import/no-internal-modules\nimport cloneDeep from \"lodash/cloneDeep\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n IChannel,\n IFluidDataStoreRuntime,\n IChannelFactory,\n IChannelAttributes,\n} from \"@fluidframework/datastore-definitions\";\nimport {\n IFluidDataStoreContext,\n IGarbageCollectionData,\n ISummarizeResult,\n} from \"@fluidframework/runtime-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport { DataProcessingError } from \"@fluidframework/container-utils\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport {\n createServiceEndpoints,\n IChannelContext,\n summarizeChannel,\n summarizeChannelAsync,\n} from \"./channelContext\";\nimport { ChannelDeltaConnection } from \"./channelDeltaConnection\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime\";\nimport { ChannelStorageService } from \"./channelStorageService\";\n\n/**\n * Channel context for a locally created channel\n */\nexport abstract class LocalChannelContextBase implements IChannelContext {\n public channel: IChannel | undefined;\n private globallyVisible = false;\n protected readonly pending: ISequencedDocumentMessage[] = [];\n protected factory: IChannelFactory | undefined;\n constructor(\n protected readonly id: string,\n protected readonly registry: ISharedObjectRegistry,\n protected readonly runtime: IFluidDataStoreRuntime,\n private readonly servicesGetter: () => Lazy<{\n readonly deltaConnection: ChannelDeltaConnection,\n readonly objectStorage: ChannelStorageService,\n }>,\n ) {\n }\n\n public async getChannel(): Promise<IChannel> {\n assert(this.channel !== undefined, 0x207 /* \"Channel should be defined\" */);\n return this.channel;\n }\n\n public get isLoaded(): boolean {\n return this.channel !== undefined;\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n // Connection events are ignored if the data store is not yet globallyVisible or loaded\n if (this.globallyVisible && this.isLoaded) {\n this.servicesGetter().value.deltaConnection.setConnectionState(connected);\n }\n }\n\n public processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void {\n assert(this.globallyVisible, 0x2d3 /* \"Local channel must be globally visible when processing op\" */);\n\n // A local channel may not be loaded in case where we rehydrate the container from a snapshot because of\n // delay loading. So after the container is attached and some other client joins which start generating\n // ops for this channel. So not loaded local channel can still receive ops and we store them to process later.\n if (this.isLoaded) {\n this.servicesGetter().value.deltaConnection.process(message, local, localOpMetadata);\n } else {\n assert(local === false,\n 0x189 /* \"Should always be remote because a local dds shouldn't generate ops before loading\" */);\n this.pending.push(message);\n }\n }\n\n public reSubmit(content: any, localOpMetadata: unknown) {\n assert(this.isLoaded, 0x18a /* \"Channel should be loaded to resubmit ops\" */);\n assert(this.globallyVisible, 0x2d4 /* \"Local channel must be globally visible when resubmitting op\" */);\n this.servicesGetter().value.deltaConnection.reSubmit(content, localOpMetadata);\n }\n\n public applyStashedOp() {\n throw new Error(\"no stashed ops on local channel\");\n }\n\n /**\n * Returns a summary at the current sequence number.\n * @param fullTree - true to bypass optimizations and force a full summary tree\n * @param trackState - This tells whether we should track state from this summary.\n */\n public async summarize(fullTree: boolean = false, trackState: boolean = false): Promise<ISummarizeResult> {\n assert(this.isLoaded && this.channel !== undefined, 0x18c /* \"Channel should be loaded to summarize\" */);\n return summarizeChannelAsync(this.channel, fullTree, trackState);\n }\n\n public getAttachSummary(): ISummarizeResult {\n assert(this.isLoaded && this.channel !== undefined, 0x18d /* \"Channel should be loaded to take snapshot\" */);\n return summarizeChannel(this.channel, true /* fullTree */, false /* trackState */);\n }\n\n public makeVisible(): void {\n if (this.globallyVisible) {\n throw new Error(\"Channel is already globally visible\");\n }\n\n if (this.isLoaded) {\n assert(!!this.channel, 0x192 /* \"Channel should be there if loaded!!\" */);\n this.channel.connect(this.servicesGetter().value);\n }\n this.globallyVisible = true;\n }\n\n /**\n * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.\n * Each node has a set of outbound routes to other GC nodes in the document. This should be called only after\n * the context has loaded.\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 assert(this.isLoaded && this.channel !== undefined, 0x193 /* \"Channel should be loaded to run GC\" */);\n return this.channel.getGCData(fullGC);\n }\n\n public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number) {\n /**\n * Currently, DDSs are always considered referenced and are not garbage collected.\n * Once we have GC at DDS level, this channel context's used routes will be updated as per the passed\n * value. See - https://github.com/microsoft/FluidFramework/issues/4611\n */\n }\n}\n\nexport class RehydratedLocalChannelContext extends LocalChannelContextBase {\n private readonly services: Lazy<{\n readonly deltaConnection: ChannelDeltaConnection,\n readonly objectStorage: ChannelStorageService,\n }>;\n\n private readonly dirtyFn: () => void;\n\n constructor(\n id: string,\n registry: ISharedObjectRegistry,\n runtime: IFluidDataStoreRuntime,\n dataStoreContext: IFluidDataStoreContext,\n storageService: IDocumentStorageService,\n logger: ITelemetryLogger,\n submitFn: (content: any, localOpMetadata: unknown) => void,\n dirtyFn: (address: string) => void,\n addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n private readonly snapshotTree: ISnapshotTree,\n ) {\n super(id, registry, runtime, () => this.services);\n const blobMap: Map<string, ArrayBufferLike> = new Map<string, ArrayBufferLike>();\n const clonedSnapshotTree = cloneDeep(this.snapshotTree);\n // 0.47 back-compat Need to sanitize if snapshotTree.blobs still contains blob contents too.\n // This is for older snapshot which is generated by loader <=0.47 version which still contains\n // the contents within blobs. After a couple of revisions we can remove it.\n if (this.isSnapshotInOldFormatAndCollectBlobs(clonedSnapshotTree, blobMap)) {\n this.sanitizeSnapshot(clonedSnapshotTree);\n }\n\n this.services = new Lazy(() => {\n return createServiceEndpoints(\n this.id,\n dataStoreContext.connected,\n submitFn,\n this.dirtyFn,\n addedGCOutboundReferenceFn,\n storageService,\n logger,\n clonedSnapshotTree,\n blobMap,\n );\n });\n this.dirtyFn = () => { dirtyFn(id); };\n }\n\n public async getChannel(): Promise<IChannel> {\n if (this.channel === undefined) {\n this.channel = await this.loadChannel()\n .catch((err) => {\n throw DataProcessingError.wrapIfUnrecognized(\n err, \"rehydratedLocalChannelContextFailedToLoadChannel\", undefined);\n });\n }\n return this.channel;\n }\n\n private async loadChannel(): Promise<IChannel> {\n assert(!this.isLoaded, 0x18e /* \"Channel must not already be loaded when loading\" */);\n assert(await this.services.value.objectStorage.contains(\".attributes\"),\n 0x190 /* \".attributes blob should be present\" */);\n const attributes = await readAndParse<IChannelAttributes>(\n this.services.value.objectStorage,\n \".attributes\");\n\n assert(this.factory === undefined, 0x208 /* \"Factory should be undefined before loading\" */);\n this.factory = this.registry.get(attributes.type);\n if (this.factory === undefined) {\n throw new Error(`Channel Factory ${attributes.type} not registered`);\n }\n // Services will be assigned during this load.\n const channel = await this.factory.load(\n this.runtime,\n this.id,\n this.services.value,\n attributes);\n\n // Commit changes.\n this.channel = channel;\n\n // Send all pending messages to the channel\n for (const message of this.pending) {\n this.services.value.deltaConnection.process(message, false, undefined /* localOpMetadata */);\n }\n return this.channel;\n }\n\n private isSnapshotInOldFormatAndCollectBlobs(\n snapshotTree: ISnapshotTree,\n blobMap: Map<string, ArrayBufferLike>,\n ): boolean {\n let sanitize = false;\n const blobsContents: {[path: string]: ArrayBufferLike} = (snapshotTree as any).blobsContents;\n Object.entries(blobsContents).forEach(([key, value]) => {\n blobMap.set(key, value);\n if (snapshotTree.blobs[key] !== undefined) {\n sanitize = true;\n }\n });\n for (const value of Object.values(snapshotTree.trees)) {\n sanitize = sanitize || this.isSnapshotInOldFormatAndCollectBlobs(value, blobMap);\n }\n return sanitize;\n }\n\n private sanitizeSnapshot(snapshotTree: ISnapshotTree) {\n const blobMapInitial = new Map(Object.entries(snapshotTree.blobs));\n for (const [blobName, blobId] of blobMapInitial.entries()) {\n const blobValue = blobMapInitial.get(blobId);\n if (blobValue === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete snapshotTree.blobs[blobName];\n }\n }\n for (const value of Object.values(snapshotTree.trees)) {\n this.sanitizeSnapshot(value);\n }\n }\n}\n\nexport class LocalChannelContext extends LocalChannelContextBase {\n private readonly services: Lazy<{\n readonly deltaConnection: ChannelDeltaConnection,\n readonly objectStorage: ChannelStorageService,\n }>;\n private readonly dirtyFn: () => void;\n constructor(\n id: string,\n registry: ISharedObjectRegistry,\n type: string,\n runtime: IFluidDataStoreRuntime,\n dataStoreContext: IFluidDataStoreContext,\n storageService: IDocumentStorageService,\n logger: ITelemetryLogger,\n submitFn: (content: any, localOpMetadata: unknown) => void,\n dirtyFn: (address: string) => void,\n addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n ) {\n super(id, registry, runtime, () => this.services);\n assert(type !== undefined, 0x209 /* \"Factory Type should be defined\" */);\n this.factory = registry.get(type);\n if (this.factory === undefined) {\n throw new Error(`Channel Factory ${type} not registered`);\n }\n this.channel = this.factory.create(runtime, id);\n this.services = new Lazy(() => {\n return createServiceEndpoints(\n this.id,\n dataStoreContext.connected,\n submitFn,\n this.dirtyFn,\n addedGCOutboundReferenceFn,\n storageService,\n logger,\n );\n });\n this.dirtyFn = () => { dirtyFn(id); };\n }\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -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/datastore";
|
|
8
|
-
export declare const pkgVersion = "0.
|
|
8
|
+
export declare const pkgVersion = "0.59.1000-61898";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,2BAA2B,CAAC;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,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/datastore\";\nexport const pkgVersion = \"0.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,2BAA2B,CAAC;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,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/datastore\";\nexport const pkgVersion = \"0.59.1000-61898\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/datastore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.1000-61898",
|
|
4
4
|
"description": "Fluid data store implementation",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -62,27 +62,27 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
64
64
|
"@fluidframework/common-utils": "^0.32.1",
|
|
65
|
-
"@fluidframework/container-definitions": "^0.
|
|
66
|
-
"@fluidframework/container-utils": "0.
|
|
67
|
-
"@fluidframework/core-interfaces": "^0.
|
|
68
|
-
"@fluidframework/datastore-definitions": "0.
|
|
69
|
-
"@fluidframework/driver-definitions": "^0.
|
|
70
|
-
"@fluidframework/driver-utils": "0.
|
|
71
|
-
"@fluidframework/garbage-collector": "0.
|
|
72
|
-
"@fluidframework/protocol-base": "^0.
|
|
73
|
-
"@fluidframework/protocol-definitions": "^0.
|
|
74
|
-
"@fluidframework/runtime-definitions": "0.
|
|
75
|
-
"@fluidframework/runtime-utils": "0.
|
|
76
|
-
"@fluidframework/telemetry-utils": "0.
|
|
65
|
+
"@fluidframework/container-definitions": "^0.48.1000-0",
|
|
66
|
+
"@fluidframework/container-utils": "0.59.1000-61898",
|
|
67
|
+
"@fluidframework/core-interfaces": "^0.43.1000-0",
|
|
68
|
+
"@fluidframework/datastore-definitions": "0.59.1000-61898",
|
|
69
|
+
"@fluidframework/driver-definitions": "^0.46.1000-0",
|
|
70
|
+
"@fluidframework/driver-utils": "0.59.1000-61898",
|
|
71
|
+
"@fluidframework/garbage-collector": "0.59.1000-61898",
|
|
72
|
+
"@fluidframework/protocol-base": "^0.1036.1000-0",
|
|
73
|
+
"@fluidframework/protocol-definitions": "^0.1028.1000-0",
|
|
74
|
+
"@fluidframework/runtime-definitions": "0.59.1000-61898",
|
|
75
|
+
"@fluidframework/runtime-utils": "0.59.1000-61898",
|
|
76
|
+
"@fluidframework/telemetry-utils": "0.59.1000-61898",
|
|
77
77
|
"lodash": "^4.17.21",
|
|
78
78
|
"uuid": "^8.3.1"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@fluidframework/build-common": "^0.23.0",
|
|
82
|
-
"@fluidframework/datastore-previous": "npm:@fluidframework/datastore
|
|
83
|
-
"@fluidframework/eslint-config-fluid": "^0.
|
|
84
|
-
"@fluidframework/mocha-test-setup": "0.
|
|
85
|
-
"@fluidframework/test-runtime-utils": "0.
|
|
82
|
+
"@fluidframework/datastore-previous": "npm:@fluidframework/datastore@^0.58.0",
|
|
83
|
+
"@fluidframework/eslint-config-fluid": "^0.28.1000-61189",
|
|
84
|
+
"@fluidframework/mocha-test-setup": "0.59.1000-61898",
|
|
85
|
+
"@fluidframework/test-runtime-utils": "0.59.1000-61898",
|
|
86
86
|
"@microsoft/api-extractor": "^7.16.1",
|
|
87
87
|
"@rushstack/eslint-config": "^2.5.1",
|
|
88
88
|
"@types/mocha": "^8.2.2",
|
|
@@ -107,7 +107,13 @@
|
|
|
107
107
|
"typescript-formatter": "7.1.0"
|
|
108
108
|
},
|
|
109
109
|
"typeValidation": {
|
|
110
|
-
"version": "0.
|
|
111
|
-
"broken": {
|
|
110
|
+
"version": "0.59.1000",
|
|
111
|
+
"broken": {
|
|
112
|
+
"0.58.2002": {
|
|
113
|
+
"ClassDeclaration_FluidDataStoreRuntime": {
|
|
114
|
+
"forwardCompat": false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
112
118
|
}
|
|
113
119
|
}
|
package/src/dataStoreRuntime.ts
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
IGarbageCollectionDetailsBase,
|
|
50
50
|
IInboundSignalMessage,
|
|
51
51
|
ISummaryTreeWithStats,
|
|
52
|
+
VisibilityState,
|
|
52
53
|
} from "@fluidframework/runtime-definitions";
|
|
53
54
|
import {
|
|
54
55
|
convertSnapshotTreeToSummaryTree,
|
|
@@ -152,15 +153,14 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
152
153
|
private readonly pendingAttach = new Map<string, IAttachMessage>();
|
|
153
154
|
|
|
154
155
|
private bindState: BindState;
|
|
155
|
-
// For new data stores, this is used to break the recursion while attaching the graph. The graph must be attached
|
|
156
|
-
// before the data store can move to Attached state (see _attachState) and become live.
|
|
157
|
-
// For existing data stores, the graph is always attached.
|
|
158
|
-
private graphAttachState: AttachState = AttachState.Detached;
|
|
159
156
|
private readonly deferredAttached = new Deferred<void>();
|
|
160
157
|
private readonly localChannelContextQueue = new Map<string, LocalChannelContextBase>();
|
|
161
158
|
private readonly notBoundedChannelContextSet = new Set<string>();
|
|
162
|
-
private boundhandles: Set<IFluidHandle> | undefined;
|
|
163
159
|
private _attachState: AttachState;
|
|
160
|
+
public visibilityState: VisibilityState;
|
|
161
|
+
// A list of handles that are bound when the data store is not visible. We have to make them visible when the data
|
|
162
|
+
// store becomes visible.
|
|
163
|
+
private readonly pendingHandlesToMakeVisible: Set<IFluidHandle> = new Set();
|
|
164
164
|
|
|
165
165
|
public readonly id: string;
|
|
166
166
|
public readonly options: ILoaderOptions;
|
|
@@ -224,11 +224,11 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
224
224
|
this.addedGCOutboundReference(srcHandle, outboundHandle),
|
|
225
225
|
tree.trees[path]);
|
|
226
226
|
// This is the case of rehydrating a detached container from snapshot. Now due to delay loading of
|
|
227
|
-
// data store, if the data store is loaded after the container is attached, then we missed
|
|
228
|
-
// the channel
|
|
229
|
-
// that it can be
|
|
227
|
+
// data store, if the data store is loaded after the container is attached, then we missed making
|
|
228
|
+
// the channel visible. So do it now. Otherwise, add it to local channel context queue, so
|
|
229
|
+
// that it can be make it visible later with the data store.
|
|
230
230
|
if (dataStoreContext.attachState !== AttachState.Detached) {
|
|
231
|
-
(channelContext as LocalChannelContextBase).
|
|
231
|
+
(channelContext as LocalChannelContextBase).makeVisible();
|
|
232
232
|
} else {
|
|
233
233
|
this.localChannelContextQueue.set(path, channelContext as LocalChannelContextBase);
|
|
234
234
|
}
|
|
@@ -260,10 +260,25 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
this.attachListener();
|
|
263
|
-
// If exists on storage or loaded from a snapshot, it should already be
|
|
263
|
+
// If exists on storage or loaded from a snapshot, it should already be bound.
|
|
264
264
|
this.bindState = existing ? BindState.Bound : BindState.NotBound;
|
|
265
265
|
this._attachState = dataStoreContext.attachState;
|
|
266
266
|
|
|
267
|
+
/**
|
|
268
|
+
* If existing flag is false, this is a new data store and is not visible. The existing flag can be true in two
|
|
269
|
+
* conditions:
|
|
270
|
+
* 1. It's a local data store that is created when a detached container is rehydrated. In this case, the data
|
|
271
|
+
* store is locally visible because the snapshot it is loaded from contains locally visible data stores only.
|
|
272
|
+
* 2. It's a remote data store that is created when an attached container is loaded is loaded from snapshot or
|
|
273
|
+
* when an attach op comes in. In both these cases, the data store is already globally visible.
|
|
274
|
+
*/
|
|
275
|
+
if (existing) {
|
|
276
|
+
this.visibilityState = dataStoreContext.attachState === AttachState.Detached
|
|
277
|
+
? VisibilityState.LocallyVisible : VisibilityState.GloballyVisible;
|
|
278
|
+
} else {
|
|
279
|
+
this.visibilityState = VisibilityState.NotVisible;
|
|
280
|
+
}
|
|
281
|
+
|
|
267
282
|
// If it's existing we know it has been attached.
|
|
268
283
|
if (existing) {
|
|
269
284
|
this.deferredAttached.resolve();
|
|
@@ -377,38 +392,50 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
377
392
|
if (this.isAttached) {
|
|
378
393
|
this.attachChannel(channel);
|
|
379
394
|
return;
|
|
380
|
-
}
|
|
381
|
-
this.bind(channel.handle);
|
|
395
|
+
}
|
|
382
396
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
397
|
+
/**
|
|
398
|
+
* If this channel is already waiting to be made visible, do nothing. This can happen during attachGraph() when
|
|
399
|
+
* a channel's graph is attached. It calls bindToContext on the shared object which will end up back here.
|
|
400
|
+
*/
|
|
401
|
+
if (this.pendingHandlesToMakeVisible.has(channel.handle)) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
this.bind(channel.handle);
|
|
406
|
+
|
|
407
|
+
// If our data store is local then add the channel to the queue
|
|
408
|
+
if (!this.localChannelContextQueue.has(channel.id)) {
|
|
409
|
+
this.localChannelContextQueue.set(channel.id, this.contexts.get(channel.id) as LocalChannelContextBase);
|
|
387
410
|
}
|
|
388
411
|
}
|
|
389
412
|
|
|
390
|
-
|
|
391
|
-
|
|
413
|
+
/**
|
|
414
|
+
* This function is called when a data store becomes root. It does the following:
|
|
415
|
+
* 1. Marks the data store locally visible in the container.
|
|
416
|
+
* 2. Attaches the graph of all the handles bound to it.
|
|
417
|
+
* 3. Calls into the data store context to mark it visible in the container too. If the container is globally
|
|
418
|
+
* visible, it will mark us globally visible. Otherwise, it will mark us globally visible when it becomes
|
|
419
|
+
* globally visible.
|
|
420
|
+
*/
|
|
421
|
+
public makeVisibleAndAttachGraph() {
|
|
422
|
+
if (this.visibilityState !== VisibilityState.NotVisible) {
|
|
392
423
|
return;
|
|
393
424
|
}
|
|
394
|
-
this.
|
|
395
|
-
if (this.boundhandles !== undefined) {
|
|
396
|
-
this.boundhandles.forEach((handle) => {
|
|
397
|
-
handle.attachGraph();
|
|
398
|
-
});
|
|
399
|
-
this.boundhandles = undefined;
|
|
400
|
-
}
|
|
425
|
+
this.visibilityState = VisibilityState.LocallyVisible;
|
|
401
426
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
// When we are attaching the data store we don't need to send attach for the registered services.
|
|
405
|
-
// This is because they will be captured as part of the Attach data store snapshot
|
|
406
|
-
channel.markAttached();
|
|
427
|
+
this.pendingHandlesToMakeVisible.forEach((handle) => {
|
|
428
|
+
handle.attachGraph();
|
|
407
429
|
});
|
|
408
|
-
|
|
409
|
-
this.localChannelContextQueue.clear();
|
|
430
|
+
this.pendingHandlesToMakeVisible.clear();
|
|
410
431
|
this.bindToContext();
|
|
411
|
-
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* This function is called when a handle to this data store is added to a visible DDS.
|
|
436
|
+
*/
|
|
437
|
+
public attachGraph() {
|
|
438
|
+
this.makeVisibleAndAttachGraph();
|
|
412
439
|
}
|
|
413
440
|
|
|
414
441
|
/**
|
|
@@ -417,7 +444,7 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
417
444
|
* 1. Sending an Attach op that includes all existing state
|
|
418
445
|
* 2. Attaching the graph if the data store becomes attached.
|
|
419
446
|
*/
|
|
420
|
-
|
|
447
|
+
public bindToContext() {
|
|
421
448
|
if (this.bindState !== BindState.NotBound) {
|
|
422
449
|
return;
|
|
423
450
|
}
|
|
@@ -427,17 +454,12 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
427
454
|
}
|
|
428
455
|
|
|
429
456
|
public bind(handle: IFluidHandle): void {
|
|
430
|
-
// If
|
|
431
|
-
|
|
432
|
-
if (this.isAttached || this.graphAttachState !== AttachState.Detached) {
|
|
457
|
+
// If visible, attach the incoming handle's graph. Else, this will be done when we become visible.
|
|
458
|
+
if (this.visibilityState !== VisibilityState.NotVisible) {
|
|
433
459
|
handle.attachGraph();
|
|
434
460
|
return;
|
|
435
461
|
}
|
|
436
|
-
|
|
437
|
-
this.boundhandles = new Set<IFluidHandle>();
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
this.boundhandles.add(handle);
|
|
462
|
+
this.pendingHandlesToMakeVisible.add(handle);
|
|
441
463
|
}
|
|
442
464
|
|
|
443
465
|
public setConnectionState(connected: boolean, clientId?: string) {
|
|
@@ -587,8 +609,8 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
587
609
|
* including any of its child channel contexts. Each node has a set of outbound routes to other GC nodes in the
|
|
588
610
|
* document. It does the following:
|
|
589
611
|
* 1. Calls into each child context to get its GC data.
|
|
590
|
-
* 2.
|
|
591
|
-
*
|
|
612
|
+
* 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
|
|
613
|
+
* identified as belonging to the child.
|
|
592
614
|
* 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent
|
|
593
615
|
* the GC data of this channel.
|
|
594
616
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
|
@@ -695,8 +717,26 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
695
717
|
}
|
|
696
718
|
|
|
697
719
|
public getAttachSummary(): ISummaryTreeWithStats {
|
|
720
|
+
/**
|
|
721
|
+
* back-compat 0.59.1000 - getAttachSummary() is called when making a data store globally visible (previously
|
|
722
|
+
* attaching state). Ideally, attachGraph() should have already be called making it locally visible. However,
|
|
723
|
+
* before visibility state was added, this may not have been the case and getAttachSummary() could be called:
|
|
724
|
+
* 1) Before attaching the data store - When a detached container is attached.
|
|
725
|
+
* 2) After attaching the data store - When a data store is created and bound in an attached container.
|
|
726
|
+
*
|
|
727
|
+
* The basic idea is that all local object should become locally visible before they are globally visible.
|
|
728
|
+
*/
|
|
698
729
|
this.attachGraph();
|
|
699
730
|
|
|
731
|
+
/**
|
|
732
|
+
* This assert cannot be added now due to back-compat. To be uncommented when the following issue is fixed -
|
|
733
|
+
* https://github.com/microsoft/FluidFramework/issues/9688.
|
|
734
|
+
*
|
|
735
|
+
* assert(this.visibilityState === VisibilityState.LocallyVisible,
|
|
736
|
+
* "The data store should be locally visible when generating attach summary",
|
|
737
|
+
* );
|
|
738
|
+
*/
|
|
739
|
+
|
|
700
740
|
const summaryBuilder = new SummaryTreeBuilder();
|
|
701
741
|
|
|
702
742
|
// Craft the .attributes file for each shared object
|
|
@@ -756,24 +796,23 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
756
796
|
channel.handle.attachGraph();
|
|
757
797
|
|
|
758
798
|
assert(this.isAttached, 0x182 /* "Data store should be attached to attach the channel." */);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
799
|
+
assert(this.visibilityState === VisibilityState.GloballyVisible,
|
|
800
|
+
0x2d0 /* "Data store should be globally visible to attach channels." */);
|
|
801
|
+
|
|
802
|
+
const summarizeResult = summarizeChannel(channel, true /* fullTree */, false /* trackState */);
|
|
803
|
+
// Attach message needs the summary in ITree format. Convert the ISummaryTree into an ITree.
|
|
804
|
+
const snapshot = convertSummaryTreeToITree(summarizeResult.summary);
|
|
805
|
+
|
|
806
|
+
const message: IAttachMessage = {
|
|
807
|
+
id: channel.id,
|
|
808
|
+
snapshot,
|
|
809
|
+
type: channel.attributes.type,
|
|
810
|
+
};
|
|
811
|
+
this.pendingAttach.set(channel.id, message);
|
|
812
|
+
this.submit(DataStoreMessageType.Attach, message);
|
|
774
813
|
|
|
775
814
|
const context = this.contexts.get(channel.id) as LocalChannelContextBase;
|
|
776
|
-
context.
|
|
815
|
+
context.makeVisible();
|
|
777
816
|
}
|
|
778
817
|
|
|
779
818
|
private submitChannelOp(address: string, contents: any, localOpMetadata: unknown) {
|
|
@@ -851,16 +890,36 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
851
890
|
private attachListener() {
|
|
852
891
|
this.setMaxListeners(Number.MAX_SAFE_INTEGER);
|
|
853
892
|
this.dataStoreContext.once("attaching", () => {
|
|
854
|
-
|
|
855
|
-
|
|
893
|
+
/**
|
|
894
|
+
* back-compat 0.59.1000 - Ideally, attachGraph() should have already been called making the data store
|
|
895
|
+
* locally visible. However, before visibility state was added, this may not have been the case and data
|
|
896
|
+
* store can move to "attaching" state in 2 scenarios:
|
|
897
|
+
* 1) Before attachGraph() is called - When a data store is created and bound in an attached container.
|
|
898
|
+
* 2) After attachGraph() is called - When a detached container is attached.
|
|
899
|
+
*
|
|
900
|
+
* The basic idea is that all local object should become locally visible before they are globally visible.
|
|
901
|
+
*/
|
|
902
|
+
this.attachGraph();
|
|
903
|
+
|
|
856
904
|
this._attachState = AttachState.Attaching;
|
|
905
|
+
|
|
906
|
+
assert(this.visibilityState === VisibilityState.LocallyVisible,
|
|
907
|
+
0x2d1 /* "Data store should be locally visible before it can become globally visible." */);
|
|
908
|
+
|
|
909
|
+
// Mark the data store globally visible and make its child channels visible as well.
|
|
910
|
+
this.visibilityState = VisibilityState.GloballyVisible;
|
|
911
|
+
this.localChannelContextQueue.forEach((channel) => {
|
|
912
|
+
channel.makeVisible();
|
|
913
|
+
});
|
|
914
|
+
this.localChannelContextQueue.clear();
|
|
915
|
+
|
|
857
916
|
// This promise resolution will be moved to attached event once we fix the scheduler.
|
|
858
917
|
this.deferredAttached.resolve();
|
|
859
918
|
this.emit("attaching");
|
|
860
919
|
});
|
|
861
920
|
this.dataStoreContext.once("attached", () => {
|
|
862
|
-
assert(this.
|
|
863
|
-
|
|
921
|
+
assert(this.visibilityState === VisibilityState.GloballyVisible,
|
|
922
|
+
0x2d2 /* "Data store should be globally visible when its attached." */);
|
|
864
923
|
this._attachState = AttachState.Attached;
|
|
865
924
|
this.emit("attached");
|
|
866
925
|
});
|
package/src/fluidHandle.ts
CHANGED
|
@@ -4,18 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
IFluidObject,
|
|
8
7
|
IFluidHandle,
|
|
9
8
|
IFluidHandleContext,
|
|
10
9
|
FluidObject,
|
|
11
10
|
} from "@fluidframework/core-interfaces";
|
|
12
|
-
import { AttachState } from "@fluidframework/container-definitions";
|
|
13
11
|
import { generateHandleContextPath } from "@fluidframework/runtime-utils";
|
|
14
12
|
|
|
15
|
-
export class FluidObjectHandle<T extends FluidObject =
|
|
16
|
-
|
|
17
|
-
private graphAttachState: AttachState = AttachState.Detached;
|
|
18
|
-
private bound: Set<IFluidHandle> | undefined;
|
|
13
|
+
export class FluidObjectHandle<T extends FluidObject = FluidObject> implements IFluidHandle {
|
|
14
|
+
private readonly pendingHandlesToMakeVisible: Set<IFluidHandle> = new Set();
|
|
19
15
|
public readonly absolutePath: string;
|
|
20
16
|
|
|
21
17
|
public get IFluidHandle(): IFluidHandle { return this; }
|
|
@@ -24,6 +20,26 @@ export class FluidObjectHandle<T extends FluidObject = IFluidObject> implements
|
|
|
24
20
|
return this.routeContext.isAttached;
|
|
25
21
|
}
|
|
26
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Tells whether the object of this handle is visible in the container locally or globally.
|
|
25
|
+
*/
|
|
26
|
+
private get visible(): boolean {
|
|
27
|
+
/**
|
|
28
|
+
* If the object of this handle is attached, it is visible in the container. Ideally, checking local visibility
|
|
29
|
+
* should be enough for a handle. However, there are scenarios where the object becomes locally visible but the
|
|
30
|
+
* handle does not know this - This will happen is attachGraph is never called on the handle. Couple of examples
|
|
31
|
+
* where this can happen:
|
|
32
|
+
* 1. Handles to DDS other than the default handle won't know if the DDS becomes visible after the handle was
|
|
33
|
+
* created.
|
|
34
|
+
* 2. Handles to root data stores will never know that it was visible because the handle will not be stores in
|
|
35
|
+
* another DDS and so, attachGraph will never be called on it.
|
|
36
|
+
*/
|
|
37
|
+
return this.isAttached || this.locallyVisible;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Tracks whether this handle is locally visible in the container.
|
|
41
|
+
private locallyVisible: boolean = false;
|
|
42
|
+
|
|
27
43
|
/**
|
|
28
44
|
* Creates a new FluidObjectHandle.
|
|
29
45
|
* @param value - The FluidObject object this handle is for.
|
|
@@ -43,33 +59,24 @@ export class FluidObjectHandle<T extends FluidObject = IFluidObject> implements
|
|
|
43
59
|
}
|
|
44
60
|
|
|
45
61
|
public attachGraph(): void {
|
|
46
|
-
|
|
47
|
-
if (this.graphAttachState !== AttachState.Detached) {
|
|
62
|
+
if (this.visible) {
|
|
48
63
|
return;
|
|
49
64
|
}
|
|
50
|
-
this.graphAttachState = AttachState.Attaching;
|
|
51
|
-
if (this.bound !== undefined) {
|
|
52
|
-
for (const handle of this.bound) {
|
|
53
|
-
handle.attachGraph();
|
|
54
|
-
}
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
this.locallyVisible = true;
|
|
67
|
+
this.pendingHandlesToMakeVisible.forEach((handle) => {
|
|
68
|
+
handle.attachGraph();
|
|
69
|
+
});
|
|
70
|
+
this.pendingHandlesToMakeVisible.clear();
|
|
58
71
|
this.routeContext.attachGraph();
|
|
59
|
-
this.graphAttachState = AttachState.Attached;
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
public bind(handle: IFluidHandle) {
|
|
63
|
-
// If
|
|
64
|
-
|
|
65
|
-
if (this.isAttached || this.graphAttachState !== AttachState.Detached) {
|
|
75
|
+
// If this handle is visible, attach the graph of the incoming handle as well.
|
|
76
|
+
if (this.visible) {
|
|
66
77
|
handle.attachGraph();
|
|
67
78
|
return;
|
|
68
79
|
}
|
|
69
|
-
|
|
70
|
-
this.bound = new Set<IFluidHandle>();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
this.bound.add(handle);
|
|
80
|
+
this.pendingHandlesToMakeVisible.add(handle);
|
|
74
81
|
}
|
|
75
82
|
}
|
|
@@ -38,7 +38,7 @@ import { ChannelStorageService } from "./channelStorageService";
|
|
|
38
38
|
*/
|
|
39
39
|
export abstract class LocalChannelContextBase implements IChannelContext {
|
|
40
40
|
public channel: IChannel | undefined;
|
|
41
|
-
private
|
|
41
|
+
private globallyVisible = false;
|
|
42
42
|
protected readonly pending: ISequencedDocumentMessage[] = [];
|
|
43
43
|
protected factory: IChannelFactory | undefined;
|
|
44
44
|
constructor(
|
|
@@ -62,14 +62,14 @@ export abstract class LocalChannelContextBase implements IChannelContext {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
public setConnectionState(connected: boolean, clientId?: string) {
|
|
65
|
-
// Connection events are ignored if the data store is not yet
|
|
66
|
-
if (this.
|
|
65
|
+
// Connection events are ignored if the data store is not yet globallyVisible or loaded
|
|
66
|
+
if (this.globallyVisible && this.isLoaded) {
|
|
67
67
|
this.servicesGetter().value.deltaConnection.setConnectionState(connected);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
public processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void {
|
|
72
|
-
assert(this.
|
|
72
|
+
assert(this.globallyVisible, 0x2d3 /* "Local channel must be globally visible when processing op" */);
|
|
73
73
|
|
|
74
74
|
// A local channel may not be loaded in case where we rehydrate the container from a snapshot because of
|
|
75
75
|
// delay loading. So after the container is attached and some other client joins which start generating
|
|
@@ -85,7 +85,7 @@ export abstract class LocalChannelContextBase implements IChannelContext {
|
|
|
85
85
|
|
|
86
86
|
public reSubmit(content: any, localOpMetadata: unknown) {
|
|
87
87
|
assert(this.isLoaded, 0x18a /* "Channel should be loaded to resubmit ops" */);
|
|
88
|
-
assert(this.
|
|
88
|
+
assert(this.globallyVisible, 0x2d4 /* "Local channel must be globally visible when resubmitting op" */);
|
|
89
89
|
this.servicesGetter().value.deltaConnection.reSubmit(content, localOpMetadata);
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -108,16 +108,16 @@ export abstract class LocalChannelContextBase implements IChannelContext {
|
|
|
108
108
|
return summarizeChannel(this.channel, true /* fullTree */, false /* trackState */);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
public
|
|
112
|
-
if (this.
|
|
113
|
-
throw new Error("Channel is already
|
|
111
|
+
public makeVisible(): void {
|
|
112
|
+
if (this.globallyVisible) {
|
|
113
|
+
throw new Error("Channel is already globally visible");
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
if (this.isLoaded) {
|
|
117
117
|
assert(!!this.channel, 0x192 /* "Channel should be there if loaded!!" */);
|
|
118
118
|
this.channel.connect(this.servicesGetter().value);
|
|
119
119
|
}
|
|
120
|
-
this.
|
|
120
|
+
this.globallyVisible = true;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/**
|
package/src/packageVersion.ts
CHANGED