@fluidframework/datastore 0.59.4001 → 1.1.0-75972
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/.eslintrc.js +1 -1
- package/dist/channelContext.d.ts +5 -4
- package/dist/channelContext.d.ts.map +1 -1
- package/dist/channelContext.js +4 -4
- package/dist/channelContext.js.map +1 -1
- package/dist/channelDeltaConnection.d.ts +1 -0
- package/dist/channelDeltaConnection.d.ts.map +1 -1
- package/dist/channelDeltaConnection.js +6 -0
- package/dist/channelDeltaConnection.js.map +1 -1
- package/dist/dataStoreRuntime.d.ts +10 -3
- package/dist/dataStoreRuntime.d.ts.map +1 -1
- package/dist/dataStoreRuntime.js +33 -7
- package/dist/dataStoreRuntime.js.map +1 -1
- package/dist/localChannelContext.d.ts +5 -3
- package/dist/localChannelContext.d.ts.map +1 -1
- package/dist/localChannelContext.js +11 -4
- package/dist/localChannelContext.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/remoteChannelContext.d.ts +4 -2
- package/dist/remoteChannelContext.d.ts.map +1 -1
- package/dist/remoteChannelContext.js +11 -5
- package/dist/remoteChannelContext.js.map +1 -1
- package/lib/channelContext.d.ts +5 -4
- package/lib/channelContext.d.ts.map +1 -1
- package/lib/channelContext.js +4 -4
- package/lib/channelContext.js.map +1 -1
- package/lib/channelDeltaConnection.d.ts +1 -0
- package/lib/channelDeltaConnection.d.ts.map +1 -1
- package/lib/channelDeltaConnection.js +6 -0
- package/lib/channelDeltaConnection.js.map +1 -1
- package/lib/dataStoreRuntime.d.ts +10 -3
- package/lib/dataStoreRuntime.d.ts.map +1 -1
- package/lib/dataStoreRuntime.js +35 -9
- package/lib/dataStoreRuntime.js.map +1 -1
- package/lib/localChannelContext.d.ts +5 -3
- package/lib/localChannelContext.d.ts.map +1 -1
- package/lib/localChannelContext.js +11 -4
- package/lib/localChannelContext.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/remoteChannelContext.d.ts +4 -2
- package/lib/remoteChannelContext.d.ts.map +1 -1
- package/lib/remoteChannelContext.js +11 -5
- package/lib/remoteChannelContext.js.map +1 -1
- package/package.json +18 -31
- package/src/channelContext.ts +12 -3
- package/src/channelDeltaConnection.ts +7 -0
- package/src/dataStoreRuntime.ts +45 -8
- package/src/localChannelContext.ts +16 -4
- package/src/packageVersion.ts +1 -1
- package/src/remoteChannelContext.ts +24 -5
|
@@ -16,9 +16,10 @@ export class RemoteChannelContext {
|
|
|
16
16
|
this.attachMessageType = attachMessageType;
|
|
17
17
|
this.isLoaded = false;
|
|
18
18
|
this.pending = [];
|
|
19
|
+
assert(!this.id.includes("/"), 0x310 /* Channel context ID cannot contain slashes */);
|
|
19
20
|
this.subLogger = ChildLogger.create(this.runtime.logger, "RemoteChannelContext");
|
|
20
21
|
this.services = createServiceEndpoints(this.id, this.dataStoreContext.connected, submitFn, () => dirtyFn(this.id), addedGCOutboundReferenceFn, storageService, this.subLogger, baseSnapshot, extraBlobs);
|
|
21
|
-
const thisSummarizeInternal = async (fullTree, trackState) => this.summarizeInternal(fullTree, trackState);
|
|
22
|
+
const thisSummarizeInternal = async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext);
|
|
22
23
|
this.summarizerNode = createSummarizerNode(thisSummarizeInternal, async (fullGC) => this.getGCDataInternal(fullGC), async () => getBaseGCDetails());
|
|
23
24
|
this.thresholdOpsCounter = new ThresholdCounter(RemoteChannelContext.pendingOpsCountThreshold, this.subLogger);
|
|
24
25
|
}
|
|
@@ -56,17 +57,22 @@ export class RemoteChannelContext {
|
|
|
56
57
|
assert(this.isLoaded, 0x196 /* "Remote channel must be loaded when resubmitting op" */);
|
|
57
58
|
this.services.deltaConnection.reSubmit(content, localOpMetadata);
|
|
58
59
|
}
|
|
60
|
+
rollback(content, localOpMetadata) {
|
|
61
|
+
assert(this.isLoaded, 0x2f0 /* "Remote channel must be loaded when rolling back op" */);
|
|
62
|
+
this.services.deltaConnection.rollback(content, localOpMetadata);
|
|
63
|
+
}
|
|
59
64
|
/**
|
|
60
65
|
* Returns a summary at the current sequence number.
|
|
61
66
|
* @param fullTree - true to bypass optimizations and force a full summary tree
|
|
62
67
|
* @param trackState - This tells whether we should track state from this summary.
|
|
68
|
+
* @param telemetryContext - summary data passed through the layers for telemetry purposes
|
|
63
69
|
*/
|
|
64
|
-
async summarize(fullTree = false, trackState = true) {
|
|
65
|
-
return this.summarizerNode.summarize(fullTree, trackState);
|
|
70
|
+
async summarize(fullTree = false, trackState = true, telemetryContext) {
|
|
71
|
+
return this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
66
72
|
}
|
|
67
|
-
async summarizeInternal(fullTree, trackState) {
|
|
73
|
+
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
68
74
|
const channel = await this.getChannel();
|
|
69
|
-
const summarizeResult = await summarizeChannelAsync(channel, fullTree, trackState);
|
|
75
|
+
const summarizeResult = await summarizeChannelAsync(channel, fullTree, trackState, telemetryContext);
|
|
70
76
|
return Object.assign(Object.assign({}, summarizeResult), { id: this.id });
|
|
71
77
|
}
|
|
72
78
|
async loadChannel() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteChannelContext.js","sourceRoot":"","sources":["../src/remoteChannelContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { DataCorruptionError } from \"@fluidframework/container-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport {\n IChannel,\n IChannelAttributes,\n IFluidDataStoreRuntime,\n IChannelFactory,\n} from \"@fluidframework/datastore-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport {\n ISequencedDocumentMessage,\n ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n CreateChildSummarizerNodeFn,\n IFluidDataStoreContext,\n IGarbageCollectionData,\n IGarbageCollectionDetailsBase,\n ISummarizeInternalResult,\n ISummarizeResult,\n ISummarizerNodeWithGC,\n} from \"@fluidframework/runtime-definitions\";\nimport { ChildLogger, TelemetryDataTag, ThresholdCounter } from \"@fluidframework/telemetry-utils\";\nimport {\n attributesBlobKey,\n createServiceEndpoints,\n IChannelContext,\n summarizeChannelAsync,\n} from \"./channelContext\";\nimport { ChannelDeltaConnection } from \"./channelDeltaConnection\";\nimport { ChannelStorageService } from \"./channelStorageService\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime\";\n\nexport class RemoteChannelContext implements IChannelContext {\n private isLoaded = false;\n private pending: ISequencedDocumentMessage[] | undefined = [];\n private channelP: Promise<IChannel> | undefined;\n private channel: IChannel | undefined;\n private readonly services: {\n readonly deltaConnection: ChannelDeltaConnection;\n readonly objectStorage: ChannelStorageService;\n };\n private readonly summarizerNode: ISummarizerNodeWithGC;\n private readonly subLogger: ITelemetryLogger;\n private readonly thresholdOpsCounter: ThresholdCounter;\n private static readonly pendingOpsCountThreshold = 1000;\n\n constructor(\n private readonly runtime: IFluidDataStoreRuntime,\n private readonly dataStoreContext: IFluidDataStoreContext,\n storageService: IDocumentStorageService,\n submitFn: (content: any, localOpMetadata: unknown) => void,\n dirtyFn: (address: string) => void,\n addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n private readonly id: string,\n baseSnapshot: ISnapshotTree,\n private readonly registry: ISharedObjectRegistry,\n extraBlobs: Map<string, ArrayBufferLike> | undefined,\n createSummarizerNode: CreateChildSummarizerNodeFn,\n getBaseGCDetails: () => Promise<IGarbageCollectionDetailsBase>,\n private readonly attachMessageType?: string,\n ) {\n this.subLogger = ChildLogger.create(this.runtime.logger, \"RemoteChannelContext\");\n\n this.services = createServiceEndpoints(\n this.id,\n this.dataStoreContext.connected,\n submitFn,\n () => dirtyFn(this.id),\n addedGCOutboundReferenceFn,\n storageService,\n this.subLogger,\n baseSnapshot,\n extraBlobs);\n\n const thisSummarizeInternal =\n async (fullTree: boolean, trackState: boolean) => this.summarizeInternal(fullTree, trackState);\n\n this.summarizerNode = createSummarizerNode(\n thisSummarizeInternal,\n async (fullGC?: boolean) => this.getGCDataInternal(fullGC),\n async () => getBaseGCDetails(),\n );\n\n this.thresholdOpsCounter = new ThresholdCounter(\n RemoteChannelContext.pendingOpsCountThreshold,\n this.subLogger,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n public getChannel(): Promise<IChannel> {\n if (this.channelP === undefined) {\n this.channelP = this.loadChannel();\n }\n\n return this.channelP;\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n // Connection events are ignored if the data store is not yet loaded\n if (!this.isLoaded) {\n return;\n }\n\n this.services.deltaConnection.setConnectionState(connected);\n }\n\n public applyStashedOp(message: ISequencedDocumentMessage): unknown {\n assert(this.isLoaded, 0x194 /* \"Remote channel must be loaded when rebasing op\" */);\n return this.services.deltaConnection.applyStashedOp(message);\n }\n\n public processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void {\n this.summarizerNode.invalidate(message.sequenceNumber);\n\n if (this.isLoaded) {\n this.services.deltaConnection.process(message, local, localOpMetadata);\n } else {\n assert(!local, 0x195 /* \"Remote channel must not be local when processing op\" */);\n assert(this.pending !== undefined, 0x23e /* \"pending is undefined\" */);\n this.pending.push(message);\n this.thresholdOpsCounter.sendIfMultiple(\"StorePendingOps\", this.pending.length);\n }\n }\n\n public reSubmit(content: any, localOpMetadata: unknown) {\n assert(this.isLoaded, 0x196 /* \"Remote channel must be loaded when resubmitting op\" */);\n\n this.services.deltaConnection.reSubmit(content, localOpMetadata);\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 = true): Promise<ISummarizeResult> {\n return this.summarizerNode.summarize(fullTree, trackState);\n }\n\n private async summarizeInternal(fullTree: boolean, trackState: boolean): Promise<ISummarizeInternalResult> {\n const channel = await this.getChannel();\n const summarizeResult = await summarizeChannelAsync(channel, fullTree, trackState);\n return { ...summarizeResult, id: this.id };\n }\n\n private async loadChannel(): Promise<IChannel> {\n assert(!this.isLoaded, 0x197 /* \"Remote channel must not already be loaded when loading\" */);\n\n let attributes: IChannelAttributes | undefined;\n if (await this.services.objectStorage.contains(attributesBlobKey)) {\n attributes = await readAndParse<IChannelAttributes | undefined>(\n this.services.objectStorage,\n attributesBlobKey);\n }\n\n let factory: IChannelFactory | undefined;\n // this is a backward compatibility case where\n // the attach message doesn't include\n // the attributes. Since old attach messages\n // will not have attributes we need to keep\n // this as long as we support old attach messages\n if (attributes === undefined) {\n if (this.attachMessageType === undefined) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n throw new DataCorruptionError(\"channelTypeNotAvailable\", {\n channelId: {\n value: this.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStoreId: {\n value: this.dataStoreContext.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStorePackagePath: this.dataStoreContext.packagePath.join(\"/\"),\n });\n }\n factory = this.registry.get(this.attachMessageType);\n if (factory === undefined) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n throw new DataCorruptionError(\"channelFactoryNotRegisteredForAttachMessageType\", {\n channelId: {\n value: this.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStoreId: {\n value: this.dataStoreContext.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStorePackagePath: this.dataStoreContext.packagePath.join(\"/\"),\n channelFactoryType: this.attachMessageType,\n });\n }\n attributes = factory.attributes;\n } else {\n factory = this.registry.get(attributes.type);\n if (factory === undefined) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n throw new DataCorruptionError(\"channelFactoryNotRegisteredForGivenType\", {\n channelId: {\n value: this.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStoreId: {\n value: this.dataStoreContext.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStorePackagePath: this.dataStoreContext.packagePath.join(\"/\"),\n channelFactoryType: attributes.type,\n });\n }\n }\n\n // Compare snapshot version to collaborative object version\n if (attributes.snapshotFormatVersion !== undefined\n && attributes.snapshotFormatVersion !== factory.attributes.snapshotFormatVersion) {\n this.subLogger.sendTelemetryEvent(\n {\n eventName: \"ChannelAttributesVersionMismatch\",\n channelType: { value: attributes.type, tag: TelemetryDataTag.PackageData },\n channelSnapshotVersion: {\n value: `${attributes.snapshotFormatVersion}@${attributes.packageVersion}`,\n tag: TelemetryDataTag.PackageData,\n },\n channelCodeVersion: {\n value: `${factory.attributes.snapshotFormatVersion}@${factory.attributes.packageVersion}`,\n tag: TelemetryDataTag.PackageData,\n },\n },\n );\n }\n\n const channel = await factory.load(\n this.runtime,\n this.id,\n this.services,\n attributes);\n\n // Send all pending messages to the channel\n assert(this.pending !== undefined, 0x23f /* \"pending undefined\" */);\n for (const message of this.pending) {\n this.services.deltaConnection.process(message, false, undefined /* localOpMetadata */);\n }\n this.thresholdOpsCounter.send(\"ProcessPendingOps\", this.pending.length);\n\n // Commit changes.\n this.channel = channel;\n this.pending = undefined;\n this.isLoaded = true;\n\n // Because have some await between we created the service and here, the connection state might have changed\n // and we don't propagate the connection state when we are not loaded. So we have to set it again here.\n this.services.deltaConnection.setConnectionState(this.dataStoreContext.connected);\n return this.channel;\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.\n * If there is no new data in this context since the last summary, previous GC data is used.\n * If there is new data, the GC data is generated again (by calling getGCDataInternal).\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 return this.summarizerNode.getGCData(fullGC);\n }\n\n /**\n * Generates the data used for garbage collection. This is called when there is new data since last summary. It\n * loads the context and calls into the channel to get its GC data.\n * @param fullGC - true to bypass optimizations and force full generation of GC data.\n */\n private async getGCDataInternal(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n const channel = await this.getChannel();\n return 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. Update the summarizer node's\n * used routes to contain a route to this channel context.\n * Once we have GC at DDS level, this will be updated to use the passed usedRoutes. See -\n * https://github.com/microsoft/FluidFramework/issues/4611\n */\n this.summarizerNode.updateUsedRoutes([\"\"]);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"remoteChannelContext.js","sourceRoot":"","sources":["../src/remoteChannelContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { DataCorruptionError } from \"@fluidframework/container-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport {\n IChannel,\n IChannelAttributes,\n IFluidDataStoreRuntime,\n IChannelFactory,\n} from \"@fluidframework/datastore-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport {\n ISequencedDocumentMessage,\n ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n CreateChildSummarizerNodeFn,\n IFluidDataStoreContext,\n IGarbageCollectionData,\n IGarbageCollectionDetailsBase,\n ISummarizeInternalResult,\n ISummarizeResult,\n ISummarizerNodeWithGC,\n ITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport { ChildLogger, TelemetryDataTag, ThresholdCounter } from \"@fluidframework/telemetry-utils\";\nimport {\n attributesBlobKey,\n createServiceEndpoints,\n IChannelContext,\n summarizeChannelAsync,\n} from \"./channelContext\";\nimport { ChannelDeltaConnection } from \"./channelDeltaConnection\";\nimport { ChannelStorageService } from \"./channelStorageService\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime\";\n\nexport class RemoteChannelContext implements IChannelContext {\n private isLoaded = false;\n private pending: ISequencedDocumentMessage[] | undefined = [];\n private channelP: Promise<IChannel> | undefined;\n private channel: IChannel | undefined;\n private readonly services: {\n readonly deltaConnection: ChannelDeltaConnection;\n readonly objectStorage: ChannelStorageService;\n };\n private readonly summarizerNode: ISummarizerNodeWithGC;\n private readonly subLogger: ITelemetryLogger;\n private readonly thresholdOpsCounter: ThresholdCounter;\n private static readonly pendingOpsCountThreshold = 1000;\n\n constructor(\n private readonly runtime: IFluidDataStoreRuntime,\n private readonly dataStoreContext: IFluidDataStoreContext,\n storageService: IDocumentStorageService,\n submitFn: (content: any, localOpMetadata: unknown) => void,\n dirtyFn: (address: string) => void,\n addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n private readonly id: string,\n baseSnapshot: ISnapshotTree,\n private readonly registry: ISharedObjectRegistry,\n extraBlobs: Map<string, ArrayBufferLike> | undefined,\n createSummarizerNode: CreateChildSummarizerNodeFn,\n getBaseGCDetails: () => Promise<IGarbageCollectionDetailsBase>,\n private readonly attachMessageType?: string,\n ) {\n assert(!this.id.includes(\"/\"), 0x310 /* Channel context ID cannot contain slashes */);\n\n this.subLogger = ChildLogger.create(this.runtime.logger, \"RemoteChannelContext\");\n\n this.services = createServiceEndpoints(\n this.id,\n this.dataStoreContext.connected,\n submitFn,\n () => dirtyFn(this.id),\n addedGCOutboundReferenceFn,\n storageService,\n this.subLogger,\n baseSnapshot,\n extraBlobs);\n\n const thisSummarizeInternal =\n async (fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext) =>\n this.summarizeInternal(fullTree, trackState, telemetryContext);\n\n this.summarizerNode = createSummarizerNode(\n thisSummarizeInternal,\n async (fullGC?: boolean) => this.getGCDataInternal(fullGC),\n async () => getBaseGCDetails(),\n );\n\n this.thresholdOpsCounter = new ThresholdCounter(\n RemoteChannelContext.pendingOpsCountThreshold,\n this.subLogger,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n public getChannel(): Promise<IChannel> {\n if (this.channelP === undefined) {\n this.channelP = this.loadChannel();\n }\n\n return this.channelP;\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n // Connection events are ignored if the data store is not yet loaded\n if (!this.isLoaded) {\n return;\n }\n\n this.services.deltaConnection.setConnectionState(connected);\n }\n\n public applyStashedOp(message: ISequencedDocumentMessage): unknown {\n assert(this.isLoaded, 0x194 /* \"Remote channel must be loaded when rebasing op\" */);\n return this.services.deltaConnection.applyStashedOp(message);\n }\n\n public processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void {\n this.summarizerNode.invalidate(message.sequenceNumber);\n\n if (this.isLoaded) {\n this.services.deltaConnection.process(message, local, localOpMetadata);\n } else {\n assert(!local, 0x195 /* \"Remote channel must not be local when processing op\" */);\n assert(this.pending !== undefined, 0x23e /* \"pending is undefined\" */);\n this.pending.push(message);\n this.thresholdOpsCounter.sendIfMultiple(\"StorePendingOps\", this.pending.length);\n }\n }\n\n public reSubmit(content: any, localOpMetadata: unknown) {\n assert(this.isLoaded, 0x196 /* \"Remote channel must be loaded when resubmitting op\" */);\n\n this.services.deltaConnection.reSubmit(content, localOpMetadata);\n }\n\n public rollback(content: any, localOpMetadata: unknown) {\n assert(this.isLoaded, 0x2f0 /* \"Remote channel must be loaded when rolling back op\" */);\n\n this.services.deltaConnection.rollback(content, localOpMetadata);\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 * @param telemetryContext - summary data passed through the layers for telemetry purposes\n */\n public async summarize(\n fullTree: boolean = false,\n trackState: boolean = true,\n telemetryContext?: ITelemetryContext,\n ): Promise<ISummarizeResult> {\n return this.summarizerNode.summarize(fullTree, trackState, telemetryContext);\n }\n\n private async summarizeInternal(\n fullTree: boolean,\n trackState: boolean,\n telemetryContext?: ITelemetryContext,\n ): Promise<ISummarizeInternalResult> {\n const channel = await this.getChannel();\n const summarizeResult = await summarizeChannelAsync(channel, fullTree, trackState, telemetryContext);\n return { ...summarizeResult, id: this.id };\n }\n\n private async loadChannel(): Promise<IChannel> {\n assert(!this.isLoaded, 0x197 /* \"Remote channel must not already be loaded when loading\" */);\n\n let attributes: IChannelAttributes | undefined;\n if (await this.services.objectStorage.contains(attributesBlobKey)) {\n attributes = await readAndParse<IChannelAttributes | undefined>(\n this.services.objectStorage,\n attributesBlobKey);\n }\n\n let factory: IChannelFactory | undefined;\n // this is a backward compatibility case where\n // the attach message doesn't include\n // the attributes. Since old attach messages\n // will not have attributes we need to keep\n // this as long as we support old attach messages\n if (attributes === undefined) {\n if (this.attachMessageType === undefined) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n throw new DataCorruptionError(\"channelTypeNotAvailable\", {\n channelId: {\n value: this.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStoreId: {\n value: this.dataStoreContext.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStorePackagePath: this.dataStoreContext.packagePath.join(\"/\"),\n });\n }\n factory = this.registry.get(this.attachMessageType);\n if (factory === undefined) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n throw new DataCorruptionError(\"channelFactoryNotRegisteredForAttachMessageType\", {\n channelId: {\n value: this.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStoreId: {\n value: this.dataStoreContext.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStorePackagePath: this.dataStoreContext.packagePath.join(\"/\"),\n channelFactoryType: this.attachMessageType,\n });\n }\n attributes = factory.attributes;\n } else {\n factory = this.registry.get(attributes.type);\n if (factory === undefined) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n throw new DataCorruptionError(\"channelFactoryNotRegisteredForGivenType\", {\n channelId: {\n value: this.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStoreId: {\n value: this.dataStoreContext.id,\n tag: TelemetryDataTag.PackageData,\n },\n dataStorePackagePath: this.dataStoreContext.packagePath.join(\"/\"),\n channelFactoryType: attributes.type,\n });\n }\n }\n\n // Compare snapshot version to collaborative object version\n if (attributes.snapshotFormatVersion !== undefined\n && attributes.snapshotFormatVersion !== factory.attributes.snapshotFormatVersion) {\n this.subLogger.sendTelemetryEvent(\n {\n eventName: \"ChannelAttributesVersionMismatch\",\n channelType: { value: attributes.type, tag: TelemetryDataTag.PackageData },\n channelSnapshotVersion: {\n value: `${attributes.snapshotFormatVersion}@${attributes.packageVersion}`,\n tag: TelemetryDataTag.PackageData,\n },\n channelCodeVersion: {\n value: `${factory.attributes.snapshotFormatVersion}@${factory.attributes.packageVersion}`,\n tag: TelemetryDataTag.PackageData,\n },\n },\n );\n }\n\n const channel = await factory.load(\n this.runtime,\n this.id,\n this.services,\n attributes);\n\n // Send all pending messages to the channel\n assert(this.pending !== undefined, 0x23f /* \"pending undefined\" */);\n for (const message of this.pending) {\n this.services.deltaConnection.process(message, false, undefined /* localOpMetadata */);\n }\n this.thresholdOpsCounter.send(\"ProcessPendingOps\", this.pending.length);\n\n // Commit changes.\n this.channel = channel;\n this.pending = undefined;\n this.isLoaded = true;\n\n // Because have some await between we created the service and here, the connection state might have changed\n // and we don't propagate the connection state when we are not loaded. So we have to set it again here.\n this.services.deltaConnection.setConnectionState(this.dataStoreContext.connected);\n return this.channel;\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.\n * If there is no new data in this context since the last summary, previous GC data is used.\n * If there is new data, the GC data is generated again (by calling getGCDataInternal).\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 return this.summarizerNode.getGCData(fullGC);\n }\n\n /**\n * Generates the data used for garbage collection. This is called when there is new data since last summary. It\n * loads the context and calls into the channel to get its GC data.\n * @param fullGC - true to bypass optimizations and force full generation of GC data.\n */\n private async getGCDataInternal(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n const channel = await this.getChannel();\n return 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. Update the summarizer node's\n * used routes to contain a route to this channel context.\n * Once we have GC at DDS level, this will be updated to use the passed usedRoutes. See -\n * https://github.com/microsoft/FluidFramework/issues/4611\n */\n this.summarizerNode.updateUsedRoutes([\"\"]);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/datastore",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0-75972",
|
|
4
4
|
"description": "Fluid data store implementation",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -63,50 +63,37 @@
|
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
65
65
|
"@fluidframework/common-utils": "^0.32.1",
|
|
66
|
-
"@fluidframework/container-definitions": "
|
|
67
|
-
"@fluidframework/container-utils": "
|
|
68
|
-
"@fluidframework/core-interfaces": "
|
|
69
|
-
"@fluidframework/datastore-definitions": "
|
|
70
|
-
"@fluidframework/driver-definitions": "
|
|
71
|
-
"@fluidframework/driver-utils": "
|
|
72
|
-
"@fluidframework/garbage-collector": "
|
|
73
|
-
"@fluidframework/protocol-base": "^0.1036.
|
|
66
|
+
"@fluidframework/container-definitions": "1.1.0-75972",
|
|
67
|
+
"@fluidframework/container-utils": "1.1.0-75972",
|
|
68
|
+
"@fluidframework/core-interfaces": "1.1.0-75972",
|
|
69
|
+
"@fluidframework/datastore-definitions": "1.1.0-75972",
|
|
70
|
+
"@fluidframework/driver-definitions": "1.1.0-75972",
|
|
71
|
+
"@fluidframework/driver-utils": "1.1.0-75972",
|
|
72
|
+
"@fluidframework/garbage-collector": "1.1.0-75972",
|
|
73
|
+
"@fluidframework/protocol-base": "^0.1036.5000-0",
|
|
74
74
|
"@fluidframework/protocol-definitions": "^0.1028.2000",
|
|
75
|
-
"@fluidframework/runtime-definitions": "
|
|
76
|
-
"@fluidframework/runtime-utils": "
|
|
77
|
-
"@fluidframework/telemetry-utils": "
|
|
75
|
+
"@fluidframework/runtime-definitions": "1.1.0-75972",
|
|
76
|
+
"@fluidframework/runtime-utils": "1.1.0-75972",
|
|
77
|
+
"@fluidframework/telemetry-utils": "1.1.0-75972",
|
|
78
78
|
"lodash": "^4.17.21",
|
|
79
79
|
"uuid": "^8.3.1"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@fluidframework/build-common": "^0.
|
|
83
|
-
"@fluidframework/build-tools": "^0.2.
|
|
84
|
-
"@fluidframework/datastore-previous": "npm:@fluidframework/datastore
|
|
82
|
+
"@fluidframework/build-common": "^0.24.0-0",
|
|
83
|
+
"@fluidframework/build-tools": "^0.2.71273",
|
|
84
|
+
"@fluidframework/datastore-previous": "npm:@fluidframework/datastore@^1.0.0",
|
|
85
85
|
"@fluidframework/eslint-config-fluid": "^0.28.2000",
|
|
86
|
-
"@fluidframework/mocha-test-setup": "
|
|
87
|
-
"@fluidframework/test-runtime-utils": "
|
|
86
|
+
"@fluidframework/mocha-test-setup": "1.1.0-75972",
|
|
87
|
+
"@fluidframework/test-runtime-utils": "1.1.0-75972",
|
|
88
88
|
"@microsoft/api-extractor": "^7.22.2",
|
|
89
89
|
"@rushstack/eslint-config": "^2.5.1",
|
|
90
90
|
"@types/mocha": "^9.1.1",
|
|
91
91
|
"@types/node": "^14.18.0",
|
|
92
92
|
"@types/uuid": "^8.3.0",
|
|
93
|
-
"@typescript-eslint/eslint-plugin": "~5.9.0",
|
|
94
|
-
"@typescript-eslint/parser": "~5.9.0",
|
|
95
93
|
"concurrently": "^6.2.0",
|
|
96
94
|
"copyfiles": "^2.1.0",
|
|
97
95
|
"cross-env": "^7.0.2",
|
|
98
96
|
"eslint": "~8.6.0",
|
|
99
|
-
"eslint-plugin-editorconfig": "~3.2.0",
|
|
100
|
-
"eslint-plugin-eslint-comments": "~3.2.0",
|
|
101
|
-
"eslint-plugin-import": "~2.25.4",
|
|
102
|
-
"eslint-plugin-jest": "~26.1.3",
|
|
103
|
-
"eslint-plugin-jsdoc": "~39.3.0",
|
|
104
|
-
"eslint-plugin-mocha": "~10.0.3",
|
|
105
|
-
"eslint-plugin-promise": "~6.0.0",
|
|
106
|
-
"eslint-plugin-react": "~7.28.0",
|
|
107
|
-
"eslint-plugin-tsdoc": "~0.2.14",
|
|
108
|
-
"eslint-plugin-unicorn": "~40.0.0",
|
|
109
|
-
"eslint-plugin-unused-imports": "~2.0.0",
|
|
110
97
|
"mocha": "^10.0.0",
|
|
111
98
|
"nyc": "^15.0.0",
|
|
112
99
|
"rimraf": "^2.6.2",
|
|
@@ -114,7 +101,7 @@
|
|
|
114
101
|
"typescript-formatter": "7.1.0"
|
|
115
102
|
},
|
|
116
103
|
"typeValidation": {
|
|
117
|
-
"version": "
|
|
104
|
+
"version": "1.1.0",
|
|
118
105
|
"broken": {}
|
|
119
106
|
}
|
|
120
107
|
}
|
package/src/channelContext.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
IGarbageCollectionData,
|
|
13
13
|
ISummarizeResult,
|
|
14
14
|
ISummaryTreeWithStats,
|
|
15
|
+
ITelemetryContext,
|
|
15
16
|
} from "@fluidframework/runtime-definitions";
|
|
16
17
|
import { addBlobToSummary } from "@fluidframework/runtime-utils";
|
|
17
18
|
import { ChannelDeltaConnection } from "./channelDeltaConnection";
|
|
@@ -26,12 +27,18 @@ export interface IChannelContext {
|
|
|
26
27
|
|
|
27
28
|
processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata?: unknown): void;
|
|
28
29
|
|
|
29
|
-
summarize(
|
|
30
|
+
summarize(
|
|
31
|
+
fullTree?: boolean,
|
|
32
|
+
trackState?: boolean,
|
|
33
|
+
telemetryContext?: ITelemetryContext,
|
|
34
|
+
): Promise<ISummarizeResult>;
|
|
30
35
|
|
|
31
36
|
reSubmit(content: any, localOpMetadata: unknown): void;
|
|
32
37
|
|
|
33
38
|
applyStashedOp(content: any): unknown;
|
|
34
39
|
|
|
40
|
+
rollback(message: any, localOpMetadata: unknown): void;
|
|
41
|
+
|
|
35
42
|
/**
|
|
36
43
|
* Returns the data used for garbage collection. This includes a list of GC nodes that represent this context
|
|
37
44
|
* including any of its children. Each node has a set of outbound routes to other GC nodes in the document.
|
|
@@ -78,8 +85,9 @@ export function summarizeChannel(
|
|
|
78
85
|
channel: IChannel,
|
|
79
86
|
fullTree: boolean = false,
|
|
80
87
|
trackState: boolean = false,
|
|
88
|
+
telemetryContext?: ITelemetryContext,
|
|
81
89
|
): ISummaryTreeWithStats {
|
|
82
|
-
const summarizeResult = channel.getAttachSummary(fullTree, trackState);
|
|
90
|
+
const summarizeResult = channel.getAttachSummary(fullTree, trackState, telemetryContext);
|
|
83
91
|
|
|
84
92
|
// Add the channel attributes to the returned result.
|
|
85
93
|
addBlobToSummary(summarizeResult, attributesBlobKey, JSON.stringify(channel.attributes));
|
|
@@ -90,8 +98,9 @@ export async function summarizeChannelAsync(
|
|
|
90
98
|
channel: IChannel,
|
|
91
99
|
fullTree: boolean = false,
|
|
92
100
|
trackState: boolean = false,
|
|
101
|
+
telemetryContext?: ITelemetryContext,
|
|
93
102
|
): Promise<ISummaryTreeWithStats> {
|
|
94
|
-
const summarizeResult = await channel.summarize(fullTree, trackState);
|
|
103
|
+
const summarizeResult = await channel.summarize(fullTree, trackState, telemetryContext);
|
|
95
104
|
|
|
96
105
|
// Add the channel attributes to the returned result.
|
|
97
106
|
addBlobToSummary(summarizeResult, attributesBlobKey, JSON.stringify(channel.attributes));
|
|
@@ -52,6 +52,13 @@ export class ChannelDeltaConnection implements IDeltaConnection {
|
|
|
52
52
|
this.handler.reSubmit(content, localOpMetadata);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
public rollback(content: any, localOpMetadata: unknown) {
|
|
56
|
+
if (this.handler.rollback === undefined) {
|
|
57
|
+
throw new Error("Handler doesn't support rollback");
|
|
58
|
+
}
|
|
59
|
+
this.handler.rollback(content, localOpMetadata);
|
|
60
|
+
}
|
|
61
|
+
|
|
55
62
|
public applyStashedOp(message: ISequencedDocumentMessage): unknown {
|
|
56
63
|
return this.handler.applyStashedOp(message);
|
|
57
64
|
}
|
package/src/dataStoreRuntime.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
AttachState,
|
|
18
18
|
ILoaderOptions,
|
|
19
19
|
} from "@fluidframework/container-definitions";
|
|
20
|
-
import { DataProcessingError } from "@fluidframework/container-utils";
|
|
20
|
+
import { DataProcessingError, UsageError } from "@fluidframework/container-utils";
|
|
21
21
|
import {
|
|
22
22
|
assert,
|
|
23
23
|
Deferred,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from "@fluidframework/common-utils";
|
|
28
28
|
import {
|
|
29
29
|
ChildLogger,
|
|
30
|
+
LoggingError,
|
|
30
31
|
raiseConnectedEvent,
|
|
31
32
|
} from "@fluidframework/telemetry-utils";
|
|
32
33
|
import { buildSnapshotTree } from "@fluidframework/driver-utils";
|
|
@@ -50,6 +51,7 @@ import {
|
|
|
50
51
|
IInboundSignalMessage,
|
|
51
52
|
ISummaryTreeWithStats,
|
|
52
53
|
VisibilityState,
|
|
54
|
+
ITelemetryContext,
|
|
53
55
|
} from "@fluidframework/runtime-definitions";
|
|
54
56
|
import {
|
|
55
57
|
convertSnapshotTreeToSummaryTree,
|
|
@@ -181,6 +183,9 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
181
183
|
) {
|
|
182
184
|
super();
|
|
183
185
|
|
|
186
|
+
assert(!dataStoreContext.id.includes("/"),
|
|
187
|
+
0x30e /* Id cannot contain slashes. DataStoreContext should have validated this. */);
|
|
188
|
+
|
|
184
189
|
this.logger = ChildLogger.create(
|
|
185
190
|
dataStoreContext.logger,
|
|
186
191
|
"FluidDataStoreRuntime",
|
|
@@ -349,6 +354,10 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
349
354
|
}
|
|
350
355
|
|
|
351
356
|
public createChannel(id: string = uuid(), type: string): IChannel {
|
|
357
|
+
if (id.includes("/")) {
|
|
358
|
+
throw new UsageError(`Id cannot contain slashes: ${id}`);
|
|
359
|
+
}
|
|
360
|
+
|
|
352
361
|
this.verifyNotClosed();
|
|
353
362
|
|
|
354
363
|
assert(!this.contexts.has(id), 0x179 /* "createChannel() with existing ID" */);
|
|
@@ -694,8 +703,13 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
694
703
|
* Returns a summary at the current sequence number.
|
|
695
704
|
* @param fullTree - true to bypass optimizations and force a full summary tree
|
|
696
705
|
* @param trackState - This tells whether we should track state from this summary.
|
|
706
|
+
* @param telemetryContext - summary data passed through the layers for telemetry purposes
|
|
697
707
|
*/
|
|
698
|
-
public async summarize(
|
|
708
|
+
public async summarize(
|
|
709
|
+
fullTree: boolean = false,
|
|
710
|
+
trackState: boolean = true,
|
|
711
|
+
telemetryContext?: ITelemetryContext,
|
|
712
|
+
): Promise<ISummaryTreeWithStats> {
|
|
699
713
|
const summaryBuilder = new SummaryTreeBuilder();
|
|
700
714
|
|
|
701
715
|
// Iterate over each data store and ask it to summarize
|
|
@@ -708,14 +722,14 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
708
722
|
// (i.e. it has a base mapping) - then we go ahead and summarize
|
|
709
723
|
return isAttached;
|
|
710
724
|
}).map(async ([contextId, context]) => {
|
|
711
|
-
const contextSummary = await context.summarize(fullTree, trackState);
|
|
725
|
+
const contextSummary = await context.summarize(fullTree, trackState, telemetryContext);
|
|
712
726
|
summaryBuilder.addWithStats(contextId, contextSummary);
|
|
713
727
|
}));
|
|
714
728
|
|
|
715
729
|
return summaryBuilder.getSummaryTree();
|
|
716
730
|
}
|
|
717
731
|
|
|
718
|
-
public getAttachSummary(): ISummaryTreeWithStats {
|
|
732
|
+
public getAttachSummary(telemetryContext?: ITelemetryContext): ISummaryTreeWithStats {
|
|
719
733
|
/**
|
|
720
734
|
* back-compat 0.59.1000 - getAttachSummary() is called when making a data store globally visible (previously
|
|
721
735
|
* attaching state). Ideally, attachGraph() should have already be called making it locally visible. However,
|
|
@@ -741,13 +755,13 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
741
755
|
// Craft the .attributes file for each shared object
|
|
742
756
|
for (const [contextId, context] of this.contexts) {
|
|
743
757
|
if (!(context instanceof LocalChannelContextBase)) {
|
|
744
|
-
throw new
|
|
758
|
+
throw new LoggingError("Should only be called with local channel handles");
|
|
745
759
|
}
|
|
746
760
|
|
|
747
761
|
if (!this.notBoundedChannelContextSet.has(contextId)) {
|
|
748
762
|
let summaryTree: ISummaryTreeWithStats;
|
|
749
763
|
if (context.isLoaded) {
|
|
750
|
-
const contextSummary = context.getAttachSummary();
|
|
764
|
+
const contextSummary = context.getAttachSummary(telemetryContext);
|
|
751
765
|
assert(
|
|
752
766
|
contextSummary.summary.type === SummaryType.Tree,
|
|
753
767
|
0x180 /* "getAttachSummary should always return a tree" */);
|
|
@@ -856,6 +870,29 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
856
870
|
}
|
|
857
871
|
}
|
|
858
872
|
|
|
873
|
+
/**
|
|
874
|
+
* Revert a local op.
|
|
875
|
+
* @param content - The content of the original message.
|
|
876
|
+
* @param localOpMetadata - The local metadata associated with the original message.
|
|
877
|
+
*/
|
|
878
|
+
public rollback?(type: DataStoreMessageType, content: any, localOpMetadata: unknown) {
|
|
879
|
+
this.verifyNotClosed();
|
|
880
|
+
|
|
881
|
+
switch (type) {
|
|
882
|
+
case DataStoreMessageType.ChannelOp:
|
|
883
|
+
{
|
|
884
|
+
// For Operations, find the right channel and trigger resubmission on it.
|
|
885
|
+
const envelope = content as IEnvelope;
|
|
886
|
+
const channelContext = this.contexts.get(envelope.address);
|
|
887
|
+
assert(!!channelContext, 0x2ed /* "There should be a channel context for the op" */);
|
|
888
|
+
channelContext.rollback(envelope.contents, localOpMetadata);
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
default:
|
|
892
|
+
throw new LoggingError(`Can't rollback ${type} message`);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
859
896
|
public async applyStashedOp(content: any): Promise<unknown> {
|
|
860
897
|
const envelope = content as IEnvelope;
|
|
861
898
|
const channelContext = this.contexts.get(envelope.address);
|
|
@@ -926,7 +963,7 @@ IFluidDataStoreChannel, IFluidDataStoreRuntime, IFluidHandleContext {
|
|
|
926
963
|
|
|
927
964
|
private verifyNotClosed() {
|
|
928
965
|
if (this._disposed) {
|
|
929
|
-
throw new
|
|
966
|
+
throw new LoggingError("Runtime is closed");
|
|
930
967
|
}
|
|
931
968
|
}
|
|
932
969
|
}
|
|
@@ -963,7 +1000,7 @@ export const mixinSummaryHandler = (
|
|
|
963
1000
|
private addBlob(summary: ISummaryTreeWithStats, path: string[], content: string) {
|
|
964
1001
|
const firstName = path.shift();
|
|
965
1002
|
if (firstName === undefined) {
|
|
966
|
-
throw new
|
|
1003
|
+
throw new LoggingError("Path can't be empty");
|
|
967
1004
|
}
|
|
968
1005
|
|
|
969
1006
|
let blob: ISummaryTree | ISummaryBlob = {
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
IFluidDataStoreContext,
|
|
19
19
|
IGarbageCollectionData,
|
|
20
20
|
ISummarizeResult,
|
|
21
|
+
ITelemetryContext,
|
|
21
22
|
} from "@fluidframework/runtime-definitions";
|
|
22
23
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
23
24
|
import { DataProcessingError } from "@fluidframework/container-utils";
|
|
@@ -50,6 +51,7 @@ export abstract class LocalChannelContextBase implements IChannelContext {
|
|
|
50
51
|
readonly objectStorage: ChannelStorageService;
|
|
51
52
|
}>,
|
|
52
53
|
) {
|
|
54
|
+
assert(!this.id.includes("/"), 0x30f /* Channel context ID cannot contain slashes */);
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
public async getChannel(): Promise<IChannel> {
|
|
@@ -88,6 +90,11 @@ export abstract class LocalChannelContextBase implements IChannelContext {
|
|
|
88
90
|
assert(this.globallyVisible, 0x2d4 /* "Local channel must be globally visible when resubmitting op" */);
|
|
89
91
|
this.servicesGetter().value.deltaConnection.reSubmit(content, localOpMetadata);
|
|
90
92
|
}
|
|
93
|
+
public rollback(content: any, localOpMetadata: unknown) {
|
|
94
|
+
assert(this.isLoaded, 0x2ee /* "Channel should be loaded to rollback ops" */);
|
|
95
|
+
assert(this.globallyVisible, 0x2ef /* "Local channel must be globally visible when rolling back op" */);
|
|
96
|
+
this.servicesGetter().value.deltaConnection.rollback(content, localOpMetadata);
|
|
97
|
+
}
|
|
91
98
|
|
|
92
99
|
public applyStashedOp() {
|
|
93
100
|
throw new Error("no stashed ops on local channel");
|
|
@@ -97,15 +104,20 @@ export abstract class LocalChannelContextBase implements IChannelContext {
|
|
|
97
104
|
* Returns a summary at the current sequence number.
|
|
98
105
|
* @param fullTree - true to bypass optimizations and force a full summary tree
|
|
99
106
|
* @param trackState - This tells whether we should track state from this summary.
|
|
107
|
+
* @param telemetryContext - summary data passed through the layers for telemetry purposes
|
|
100
108
|
*/
|
|
101
|
-
public async summarize(
|
|
109
|
+
public async summarize(
|
|
110
|
+
fullTree: boolean = false,
|
|
111
|
+
trackState: boolean = false,
|
|
112
|
+
telemetryContext?: ITelemetryContext,
|
|
113
|
+
): Promise<ISummarizeResult> {
|
|
102
114
|
assert(this.isLoaded && this.channel !== undefined, 0x18c /* "Channel should be loaded to summarize" */);
|
|
103
|
-
return summarizeChannelAsync(this.channel, fullTree, trackState);
|
|
115
|
+
return summarizeChannelAsync(this.channel, fullTree, trackState, telemetryContext);
|
|
104
116
|
}
|
|
105
117
|
|
|
106
|
-
public getAttachSummary(): ISummarizeResult {
|
|
118
|
+
public getAttachSummary(telemetryContext?: ITelemetryContext): ISummarizeResult {
|
|
107
119
|
assert(this.isLoaded && this.channel !== undefined, 0x18d /* "Channel should be loaded to take snapshot" */);
|
|
108
|
-
return summarizeChannel(this.channel, true /* fullTree */, false /* trackState
|
|
120
|
+
return summarizeChannel(this.channel, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
109
121
|
}
|
|
110
122
|
|
|
111
123
|
public makeVisible(): void {
|
package/src/packageVersion.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
ISummarizeInternalResult,
|
|
28
28
|
ISummarizeResult,
|
|
29
29
|
ISummarizerNodeWithGC,
|
|
30
|
+
ITelemetryContext,
|
|
30
31
|
} from "@fluidframework/runtime-definitions";
|
|
31
32
|
import { ChildLogger, TelemetryDataTag, ThresholdCounter } from "@fluidframework/telemetry-utils";
|
|
32
33
|
import {
|
|
@@ -68,6 +69,8 @@ export class RemoteChannelContext implements IChannelContext {
|
|
|
68
69
|
getBaseGCDetails: () => Promise<IGarbageCollectionDetailsBase>,
|
|
69
70
|
private readonly attachMessageType?: string,
|
|
70
71
|
) {
|
|
72
|
+
assert(!this.id.includes("/"), 0x310 /* Channel context ID cannot contain slashes */);
|
|
73
|
+
|
|
71
74
|
this.subLogger = ChildLogger.create(this.runtime.logger, "RemoteChannelContext");
|
|
72
75
|
|
|
73
76
|
this.services = createServiceEndpoints(
|
|
@@ -82,7 +85,8 @@ export class RemoteChannelContext implements IChannelContext {
|
|
|
82
85
|
extraBlobs);
|
|
83
86
|
|
|
84
87
|
const thisSummarizeInternal =
|
|
85
|
-
async (fullTree: boolean, trackState: boolean) =>
|
|
88
|
+
async (fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext) =>
|
|
89
|
+
this.summarizeInternal(fullTree, trackState, telemetryContext);
|
|
86
90
|
|
|
87
91
|
this.summarizerNode = createSummarizerNode(
|
|
88
92
|
thisSummarizeInternal,
|
|
@@ -138,18 +142,33 @@ export class RemoteChannelContext implements IChannelContext {
|
|
|
138
142
|
this.services.deltaConnection.reSubmit(content, localOpMetadata);
|
|
139
143
|
}
|
|
140
144
|
|
|
145
|
+
public rollback(content: any, localOpMetadata: unknown) {
|
|
146
|
+
assert(this.isLoaded, 0x2f0 /* "Remote channel must be loaded when rolling back op" */);
|
|
147
|
+
|
|
148
|
+
this.services.deltaConnection.rollback(content, localOpMetadata);
|
|
149
|
+
}
|
|
150
|
+
|
|
141
151
|
/**
|
|
142
152
|
* Returns a summary at the current sequence number.
|
|
143
153
|
* @param fullTree - true to bypass optimizations and force a full summary tree
|
|
144
154
|
* @param trackState - This tells whether we should track state from this summary.
|
|
155
|
+
* @param telemetryContext - summary data passed through the layers for telemetry purposes
|
|
145
156
|
*/
|
|
146
|
-
public async summarize(
|
|
147
|
-
|
|
157
|
+
public async summarize(
|
|
158
|
+
fullTree: boolean = false,
|
|
159
|
+
trackState: boolean = true,
|
|
160
|
+
telemetryContext?: ITelemetryContext,
|
|
161
|
+
): Promise<ISummarizeResult> {
|
|
162
|
+
return this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
148
163
|
}
|
|
149
164
|
|
|
150
|
-
private async summarizeInternal(
|
|
165
|
+
private async summarizeInternal(
|
|
166
|
+
fullTree: boolean,
|
|
167
|
+
trackState: boolean,
|
|
168
|
+
telemetryContext?: ITelemetryContext,
|
|
169
|
+
): Promise<ISummarizeInternalResult> {
|
|
151
170
|
const channel = await this.getChannel();
|
|
152
|
-
const summarizeResult = await summarizeChannelAsync(channel, fullTree, trackState);
|
|
171
|
+
const summarizeResult = await summarizeChannelAsync(channel, fullTree, trackState, telemetryContext);
|
|
153
172
|
return { ...summarizeResult, id: this.id };
|
|
154
173
|
}
|
|
155
174
|
|