diff --git a/.changeset/eighty-weeks-relate.md b/.changeset/eighty-weeks-relate.md new file mode 100644 index 000000000000..a7a4a623d7bc --- /dev/null +++ b/.changeset/eighty-weeks-relate.md @@ -0,0 +1,14 @@ +--- +"@fluidframework/aqueduct": minor +--- + +PureDataObject temporarily extends EventForwarder and implements IDisposable again + +`PureDataObject` extends `EventForwarder` and implements `IDìsposable` again to ease the transition to `2.0.0-internal.6.x`. +These interfaces will no longer be implemented on `PureDataObject` in version `2.0.0-internal.7.0.0`. + +The original deprecation announcement for these members can be found [here](https://github.com/microsoft/FluidFramework/releases/tag/client_v2.0.0-internal.5.2.0). + +Once the change is re-applied in `2.0.0-internal.7.0.0`, if your code was overriding any methods/properties from +`EventForwarder` and or `IDisposable` on a class that inherits (directly or transitively) from `PureDataObject`, +you'll have to remove the `override` keyword. diff --git a/.changeset/little-turkeys-sing.md b/.changeset/little-turkeys-sing.md new file mode 100644 index 000000000000..c2ff679fbbc0 --- /dev/null +++ b/.changeset/little-turkeys-sing.md @@ -0,0 +1,11 @@ +--- +"@fluidframework/container-definitions": minor +"@fluidframework/container-loader": minor +--- + +Temporarily restore id property on IContainerContext + +The `id` property on `IContainerContext` has been temporarily restored to ease the transition to `2.0.0-internal.6.x`. +It will be removed again in `2.0.0-internal.7.0.0`. + +The original deprecation announcement can be found [here](https://github.com/microsoft/FluidFramework/releases/tag/client_v2.0.0-internal.5.2.0). diff --git a/api-report/aqueduct.api.md b/api-report/aqueduct.api.md index e4d139682bea..8e41b0af57f5 100644 --- a/api-report/aqueduct.api.md +++ b/api-report/aqueduct.api.md @@ -6,6 +6,8 @@ import { AsyncFluidObjectProvider } from '@fluidframework/synthesize'; import { ContainerRuntime } from '@fluidframework/container-runtime'; +import type { EventEmitter } from 'events'; +import { EventForwarder } from '@fluidframework/common-utils'; import { FluidDataStoreRuntime } from '@fluidframework/datastore'; import { FluidObject } from '@fluidframework/core-interfaces'; import { FluidObjectSymbolProvider } from '@fluidframework/synthesize'; @@ -16,6 +18,7 @@ import { IContainerRuntime } from '@fluidframework/container-runtime-definitions import { IContainerRuntimeBase } from '@fluidframework/runtime-definitions'; import { IContainerRuntimeOptions } from '@fluidframework/container-runtime'; import { IEvent } from '@fluidframework/common-definitions'; +import { IEventProvider } from '@fluidframework/common-definitions'; import { IFluidDataStoreContext } from '@fluidframework/runtime-definitions'; import { IFluidDataStoreContextDetached } from '@fluidframework/runtime-definitions'; import { IFluidDataStoreFactory } from '@fluidframework/runtime-definitions'; @@ -36,7 +39,6 @@ import { NamedFluidDataStoreRegistryEntry } from '@fluidframework/runtime-defini import { RequestParser } from '@fluidframework/runtime-utils'; import { RuntimeFactoryHelper } from '@fluidframework/runtime-utils'; import { RuntimeRequestHandler } from '@fluidframework/request-handler'; -import { TypedEventEmitter } from '@fluidframework/common-utils'; // @public export class BaseContainerRuntimeFactory extends RuntimeFactoryHelper implements IProvideFluidDataStoreRegistry { @@ -119,10 +121,16 @@ export interface IRootDataObjectFactory extends IFluidDataStoreFactory { export const mountableViewRequestHandler: (MountableViewClass: IFluidMountableViewClass, handlers: RuntimeRequestHandler[]) => (request: RequestParser, runtime: IContainerRuntime) => Promise; // @public -export abstract class PureDataObject extends TypedEventEmitter implements IFluidLoadable, IFluidRouter, IProvideFluidHandle { +export abstract class PureDataObject extends EventForwarder implements IFluidLoadable, IFluidRouter, IProvideFluidHandle { constructor(props: IDataObjectProps); protected readonly context: IFluidDataStoreContext; + // @deprecated + dispose(): void; + // @deprecated (undocumented) + get disposed(): boolean; finishInitialization(existing: boolean): Promise; + // @deprecated (undocumented) + protected forwardEvent(source: EventEmitter | IEventProvider, ...events: string[]): void; // (undocumented) static getDataObject(runtime: IFluidDataStoreRuntime): Promise>; get handle(): IFluidHandle; @@ -142,10 +150,14 @@ export abstract class PureDataObject; // (undocumented) protected initProps?: I["InitialState"]; + // @deprecated (undocumented) + protected static isEmitterEvent(event: string): boolean; protected preInitialize(): Promise; protected readonly providers: AsyncFluidObjectProvider; request(req: IRequest): Promise; protected readonly runtime: IFluidDataStoreRuntime; + // @deprecated (undocumented) + protected unforwardEvent(source: EventEmitter | IEventProvider, ...events: string[]): void; } // @public diff --git a/api-report/container-definitions.api.md b/api-report/container-definitions.api.md index df25e8d056b2..25f5f1a6e499 100644 --- a/api-report/container-definitions.api.md +++ b/api-report/container-definitions.api.md @@ -167,6 +167,8 @@ export interface IContainerContext { getLoadedFromVersion(): IVersion | undefined; // @deprecated (undocumented) getSpecifiedCodeDetails?(): IFluidCodeDetails | undefined; + // @deprecated + readonly id: string; // (undocumented) readonly loader: ILoader; // (undocumented) diff --git a/packages/common/container-definitions/package.json b/packages/common/container-definitions/package.json index bfc10c770e8c..5c2b4d0537d8 100644 --- a/packages/common/container-definitions/package.json +++ b/packages/common/container-definitions/package.json @@ -62,6 +62,10 @@ "typescript": "~4.5.5" }, "typeValidation": { - "broken": {} + "broken": { + "InterfaceDeclaration_IContainerContext": { + "forwardCompat": false + } + } } } diff --git a/packages/common/container-definitions/src/runtime.ts b/packages/common/container-definitions/src/runtime.ts index 6e952d5dd031..0a05e93bfe79 100644 --- a/packages/common/container-definitions/src/runtime.ts +++ b/packages/common/container-definitions/src/runtime.ts @@ -197,6 +197,17 @@ export interface IContainerContext { updateDirtyContainerState(dirty: boolean): void; readonly supportedFeatures?: ReadonlyMap; + + /** + * WARNING: this id is meant for telemetry usages ONLY, not recommended for other consumption + * This id is not supposed to be exposed anywhere else. It is dependant on usage or drivers + * and scenarios which can change in the future. + * @deprecated 2.0.0-internal.5.2.0 - The docId is already logged by the {@link IContainerContext.taggedLogger} for + * telemetry purposes, so this is generally unnecessary for telemetry. + * If the id is needed for other purposes it should be passed to the consumer explicitly. + * This member will be removed in the 2.0.0-internal.7.0.0 release. + */ + readonly id: string; } export const IRuntimeFactory: keyof IProvideRuntimeFactory = "IRuntimeFactory"; diff --git a/packages/common/container-definitions/src/test/types/validateContainerDefinitionsPrevious.generated.ts b/packages/common/container-definitions/src/test/types/validateContainerDefinitionsPrevious.generated.ts index 68db7e7ba487..efb428f1de28 100644 --- a/packages/common/container-definitions/src/test/types/validateContainerDefinitionsPrevious.generated.ts +++ b/packages/common/container-definitions/src/test/types/validateContainerDefinitionsPrevious.generated.ts @@ -359,6 +359,7 @@ declare function get_old_InterfaceDeclaration_IContainerContext(): declare function use_current_InterfaceDeclaration_IContainerContext( use: TypeOnly); use_current_InterfaceDeclaration_IContainerContext( + // @ts-expect-error compatibility expected to be broken get_old_InterfaceDeclaration_IContainerContext()); /* diff --git a/packages/framework/aqueduct/package.json b/packages/framework/aqueduct/package.json index 9e0c1fd8712b..85f9a7730565 100644 --- a/packages/framework/aqueduct/package.json +++ b/packages/framework/aqueduct/package.json @@ -107,6 +107,13 @@ }, "module:es5": "es5/index.js", "typeValidation": { - "broken": {} + "broken": { + "ClassDeclaration_PureDataObject": { + "forwardCompat": false + }, + "ClassDeclaration_DataObject": { + "forwardCompat": false + } + } } } diff --git a/packages/framework/aqueduct/src/data-objects/pureDataObject.ts b/packages/framework/aqueduct/src/data-objects/pureDataObject.ts index 3acef84c020c..298614f4fa1e 100644 --- a/packages/framework/aqueduct/src/data-objects/pureDataObject.ts +++ b/packages/framework/aqueduct/src/data-objects/pureDataObject.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. */ -import { IEvent } from "@fluidframework/common-definitions"; -import { assert, TypedEventEmitter } from "@fluidframework/common-utils"; +import type { EventEmitter } from "events"; +import { IEvent, IEventProvider } from "@fluidframework/common-definitions"; +import { assert, EventForwarder } from "@fluidframework/common-utils"; import { IFluidHandle, IFluidLoadable, @@ -27,9 +28,11 @@ import { DataObjectTypes, IDataObjectProps } from "./types"; * @typeParam I - The optional input types used to strongly type the data object */ export abstract class PureDataObject - extends TypedEventEmitter + extends EventForwarder implements IFluidLoadable, IFluidRouter, IProvideFluidHandle { + private _disposed = false; + /** * This is your FluidDataStoreRuntime object */ @@ -53,6 +56,14 @@ export abstract class PureDataObject | undefined; + /** + * @deprecated 2.0.0-internal.5.2.0 - PureDataObject does not provide a functioning built-in disposed flow. + * This member will be removed in an upcoming release. + */ + public get disposed() { + return this._disposed; + } + public get id() { return this.runtime.id; } @@ -95,6 +106,12 @@ export abstract class PureDataObject { + this._disposed = true; + this.dispose(); + }); } // #region IFluidRouter @@ -175,4 +192,42 @@ export abstract class PureDataObject {} + + /** + * Called when the host container closes and disposes itself + * @deprecated 2.0.0-internal.5.2.0 - Dispose does nothing and will be removed in an upcoming release. + */ + public dispose(): void { + super.dispose(); + } + + /** + * @deprecated 2.0.0-internal.5.2.0 - PureDataObject does not actually set up to forward events, and will not be an EventForwarder + * in a future release. + */ + protected static isEmitterEvent(event: string): boolean { + return super.isEmitterEvent(event); + } + + /** + * @deprecated 2.0.0-internal.5.2.0 - PureDataObject does not actually set up to forward events, and will not be an EventForwarder + * in a future release. + */ + protected forwardEvent( + source: EventEmitter | IEventProvider, + ...events: string[] + ): void { + super.forwardEvent(source, ...events); + } + + /** + * @deprecated 2.0.0-internal.5.2.0 - PureDataObject does not actually set up to forward events, and will not be an EventForwarder + * in a future release. + */ + protected unforwardEvent( + source: EventEmitter | IEventProvider, + ...events: string[] + ): void { + super.unforwardEvent(source, ...events); + } } diff --git a/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts b/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts index 1eea3a82db61..a8b00e395ff4 100644 --- a/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts +++ b/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts @@ -71,6 +71,7 @@ declare function get_old_ClassDeclaration_DataObject(): declare function use_current_ClassDeclaration_DataObject( use: TypeOnly); use_current_ClassDeclaration_DataObject( + // @ts-expect-error compatibility expected to be broken get_old_ClassDeclaration_DataObject()); /* @@ -191,6 +192,7 @@ declare function get_old_ClassDeclaration_PureDataObject(): declare function use_current_ClassDeclaration_PureDataObject( use: TypeOnly); use_current_ClassDeclaration_PureDataObject( + // @ts-expect-error compatibility expected to be broken get_old_ClassDeclaration_PureDataObject()); /* diff --git a/packages/loader/container-loader/package.json b/packages/loader/container-loader/package.json index 82fe0e705e0f..c2cd7afb47cc 100644 --- a/packages/loader/container-loader/package.json +++ b/packages/loader/container-loader/package.json @@ -109,6 +109,10 @@ "typescript": "~4.5.5" }, "typeValidation": { - "broken": {} + "broken": { + "InterfaceDeclaration_IContainerContext": { + "forwardCompat": false + } + } } } diff --git a/packages/loader/container-loader/src/container.ts b/packages/loader/container-loader/src/container.ts index c38e6027e691..5825de5f23fd 100644 --- a/packages/loader/container-loader/src/container.ts +++ b/packages/loader/container-loader/src/container.ts @@ -2402,6 +2402,7 @@ export class Container (error?: ICriticalContainerError) => this.close(error), this.updateDirtyContainerState, this.getAbsoluteUrl, + () => this.resolvedUrl?.id, () => this.clientId, () => this.attachState, () => this.connected, diff --git a/packages/loader/container-loader/src/containerContext.ts b/packages/loader/container-loader/src/containerContext.ts index d65f0bc2ead1..41a9fc0efa56 100644 --- a/packages/loader/container-loader/src/containerContext.ts +++ b/packages/loader/container-loader/src/containerContext.ts @@ -45,6 +45,13 @@ export class ContainerContext implements IContainerContext { return this._getClientId(); } + /** + * DISCLAIMER: this id is only for telemetry purposes. Not suitable for any other usages. + */ + public get id(): string { + return this._getContainerDiagnosticId() ?? ""; + } + /** * When true, ops are free to flow * When false, ops should be kept as pending or rejected @@ -83,6 +90,7 @@ export class ContainerContext implements IContainerContext { public readonly closeFn: (error?: ICriticalContainerError) => void, public readonly updateDirtyContainerState: (dirty: boolean) => void, public readonly getAbsoluteUrl: (relativeUrl: string) => Promise, + private readonly _getContainerDiagnosticId: () => string | undefined, private readonly _getClientId: () => string | undefined, private readonly _getAttachState: () => AttachState, private readonly _getConnected: () => boolean,