diff --git a/.changeset/nice-flies-brake.md b/.changeset/nice-flies-brake.md new file mode 100644 index 000000000000..cf5a4ff834e6 --- /dev/null +++ b/.changeset/nice-flies-brake.md @@ -0,0 +1,25 @@ +--- +"@fluidframework/aqueduct": minor +"@fluidframework/container-definitions": minor +"@fluidframework/container-loader": minor +"@fluidframework/container-runtime": minor +"@fluidframework/container-runtime-definitions": minor +"@fluidframework/datastore": minor +"@fluidframework/devtools-core": minor +"@fluidframework/fluid-static": minor +"@fluidframework/runtime-definitions": minor +"@fluidframework/runtime-utils": minor +"@fluid-private/test-end-to-end-tests": minor +"@fluidframework/test-runtime-utils": minor +"@fluidframework/test-utils": minor +--- +--- +"section": legacy +--- + +The inbound and outbound properties have been removed from IDeltaManager + +The inbound and outbound properties were deprecated in a previous release and have been removed from IDeltaManager. Please check pull request [#19636](https://github.com/microsoft/FluidFramework/pull/19636) for alternative APIs. + +This is the link to the [Release Notes](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.0.0-rc.2.0.0.md#container-definitions-deprecate-ideltamanagerinbound-and-ideltamanageroutbound) +which contains more instructions on the alternatives. diff --git a/packages/common/container-definitions/api-report/container-definitions.legacy.alpha.api.md b/packages/common/container-definitions/api-report/container-definitions.legacy.alpha.api.md index b6560b694619..1a9a9854a26b 100644 --- a/packages/common/container-definitions/api-report/container-definitions.legacy.alpha.api.md +++ b/packages/common/container-definitions/api-report/container-definitions.legacy.alpha.api.md @@ -204,8 +204,6 @@ export interface IDeltaManager extends IEventProvider readonly active: boolean; readonly clientDetails: IClientDetails; readonly hasCheckpointSequenceNumber: boolean; - // @deprecated - readonly inbound: IDeltaQueue; readonly inboundSignal: IDeltaQueue; readonly initialSequenceNumber: number; readonly lastKnownSeqNumber: number; @@ -213,8 +211,6 @@ export interface IDeltaManager extends IEventProvider readonly lastSequenceNumber: number; readonly maxMessageSize: number; readonly minimumSequenceNumber: number; - // @deprecated - readonly outbound: IDeltaQueue; // (undocumented) readonly readOnlyInfo: ReadOnlyInfo; readonly serviceConfiguration: IClientConfiguration | undefined; diff --git a/packages/common/container-definitions/package.json b/packages/common/container-definitions/package.json index 4cbba3c3e653..de67c44de929 100644 --- a/packages/common/container-definitions/package.json +++ b/packages/common/container-definitions/package.json @@ -114,7 +114,17 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_IContainer": { + "backCompat": false + }, + "Interface_IContainerContext": { + "backCompat": false + }, + "Interface_IDeltaManager": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/common/container-definitions/src/deltas.ts b/packages/common/container-definitions/src/deltas.ts index 4a708cca2503..6772fb27dacb 100644 --- a/packages/common/container-definitions/src/deltas.ts +++ b/packages/common/container-definitions/src/deltas.ts @@ -156,20 +156,6 @@ export interface IDeltaManagerEvents extends IEvent { export interface IDeltaManager extends IEventProvider, IDeltaSender { - /** - * The queue of inbound delta messages - * @deprecated Do not use, for internal use only. There are a lot of complications in core pieces of the runtime - * may break if this is used directly. For example summarization and op processing. - */ - readonly inbound: IDeltaQueue; - - /** - * The queue of outbound delta messages - * @deprecated Do not use, for internal use only. There are a lot of complications in core pieces of the runtime - * may break if this is used directly. For example op submission - */ - readonly outbound: IDeltaQueue; - /** * The queue of inbound delta signals */ @@ -241,6 +227,33 @@ export interface IDeltaManager submitSignal(content: any, targetClientId?: string): void; } +/** + * DeltaManager which is used internally by the Fluid layers and not exposed to the end users. + * @internal + */ +export interface IDeltaManagerFull + extends IDeltaManager { + /** + * The queue of inbound delta messages + */ + readonly inbound: IDeltaQueue; + + /** + * The queue of outbound delta messages + */ + readonly outbound: IDeltaQueue; +} + +/** + * Type guard to check if the given deltaManager is of type {@link @fluidframework/container-definitions#IDeltaManagerFull}. + * @internal + */ +export function isIDeltaManagerFull( + deltaManager: IDeltaManager, +): deltaManager is IDeltaManagerFull { + return "inbound" in deltaManager && "outbound" in deltaManager; +} + /** * Events emitted by {@link IDeltaQueue}. * @sealed diff --git a/packages/common/container-definitions/src/index.ts b/packages/common/container-definitions/src/index.ts index 71480fdbce97..945cabe3bc41 100644 --- a/packages/common/container-definitions/src/index.ts +++ b/packages/common/container-definitions/src/index.ts @@ -19,11 +19,13 @@ export type { IConnectionDetails, IDeltaManager, IDeltaManagerEvents, + IDeltaManagerFull, IDeltaQueue, IDeltaQueueEvents, IDeltaSender, ReadOnlyInfo, } from "./deltas.js"; +export { isIDeltaManagerFull } from "./deltas.js"; export type { ContainerWarning, ICriticalContainerError } from "./error.js"; export { ContainerErrorTypes } from "./error.js"; export type { 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 b9eec20d469b..3edd6e5850cb 100644 --- a/packages/common/container-definitions/src/test/types/validateContainerDefinitionsPrevious.generated.ts +++ b/packages/common/container-definitions/src/test/types/validateContainerDefinitionsPrevious.generated.ts @@ -193,6 +193,7 @@ declare type old_as_current_for_Interface_IContainer = requireAssignableTo, TypeOnly> /* @@ -211,6 +212,7 @@ declare type old_as_current_for_Interface_IContainerContext = requireAssignableT * typeValidation.broken: * "Interface_IContainerContext": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IContainerContext = requireAssignableTo, TypeOnly> /* @@ -256,6 +258,7 @@ declare type current_as_old_for_Interface_IContainerLoadMode = requireAssignable * typeValidation.broken: * "Interface_IDeltaManager": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IDeltaManager = requireAssignableTo>, TypeOnly>> /* diff --git a/packages/framework/aqueduct/package.json b/packages/framework/aqueduct/package.json index 2b5f33a28ed6..511228d46324 100644 --- a/packages/framework/aqueduct/package.json +++ b/packages/framework/aqueduct/package.json @@ -156,7 +156,11 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_IDataObjectProps": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts b/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts index ca578b870142..8684174e0234 100644 --- a/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts +++ b/packages/framework/aqueduct/src/test/types/validateAqueductPrevious.generated.ts @@ -247,4 +247,5 @@ declare type old_as_current_for_Interface_IDataObjectProps = requireAssignableTo * typeValidation.broken: * "Interface_IDataObjectProps": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IDataObjectProps = requireAssignableTo, TypeOnly> diff --git a/packages/framework/fluid-static/package.json b/packages/framework/fluid-static/package.json index 8cbadbccc811..0f418d03260d 100644 --- a/packages/framework/fluid-static/package.json +++ b/packages/framework/fluid-static/package.json @@ -140,7 +140,11 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_IFluidContainerInternal": { + "backCompat": false + } + }, "entrypoint": "public" } } diff --git a/packages/loader/container-loader/package.json b/packages/loader/container-loader/package.json index ff36f0668ff1..9109535eebf3 100644 --- a/packages/loader/container-loader/package.json +++ b/packages/loader/container-loader/package.json @@ -216,7 +216,11 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_IContainerExperimental": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/loader/container-loader/src/container.ts b/packages/loader/container-loader/src/container.ts index 8683ef1df0b6..3577d3b42a16 100644 --- a/packages/loader/container-loader/src/container.ts +++ b/packages/loader/container-loader/src/container.ts @@ -1319,7 +1319,7 @@ export class Container ) => { try { assert( - this.deltaManager.inbound.length === 0, + this._deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */, ); return combineAppAndProtocolSummary( @@ -1523,13 +1523,13 @@ export class Container const codeDetails = this.getCodeDetailsFromQuorum(); await Promise.all([ - this.deltaManager.inbound.pause(), - this.deltaManager.inboundSignal.pause(), + this._deltaManager.inbound.pause(), + this._deltaManager.inboundSignal.pause(), ]); if ((await this.satisfies(codeDetails)) === true) { - this.deltaManager.inbound.resume(); - this.deltaManager.inboundSignal.resume(); + this._deltaManager.inbound.resume(); + this._deltaManager.inboundSignal.resume(); return; } diff --git a/packages/loader/container-loader/src/deltaManager.ts b/packages/loader/container-loader/src/deltaManager.ts index 6410283147e0..450ee5084fa8 100644 --- a/packages/loader/container-loader/src/deltaManager.ts +++ b/packages/loader/container-loader/src/deltaManager.ts @@ -5,8 +5,8 @@ import { ICriticalContainerError } from "@fluidframework/container-definitions"; import { - IDeltaManager, IDeltaManagerEvents, + IDeltaManagerFull, IDeltaQueue, type IDeltaSender, type ReadOnlyInfo, @@ -151,9 +151,7 @@ function logIfFalse( */ export class DeltaManager extends EventEmitterWithErrorHandling - implements - IDeltaManager, - IEventProvider + implements IDeltaManagerFull, IEventProvider { public readonly connectionManager: TConnectionManager; diff --git a/packages/loader/container-loader/src/index.ts b/packages/loader/container-loader/src/index.ts index da1ce6f740a5..2c53bb9b4720 100644 --- a/packages/loader/container-loader/src/index.ts +++ b/packages/loader/container-loader/src/index.ts @@ -20,7 +20,10 @@ export { resolveWithLocationRedirectionHandling, } from "./location-redirection-utilities/index.js"; export { IProtocolHandler, ProtocolHandlerBuilder } from "./protocol.js"; -export { tryParseCompatibleResolvedUrl, IParsedUrl } from "./utils.js"; +export { + tryParseCompatibleResolvedUrl, + IParsedUrl, +} from "./utils.js"; export { IBaseProtocolHandler, IScribeProtocolState, diff --git a/packages/loader/container-loader/src/loadPaused.ts b/packages/loader/container-loader/src/loadPaused.ts index a17ee4f86349..1ab27a74f543 100644 --- a/packages/loader/container-loader/src/loadPaused.ts +++ b/packages/loader/container-loader/src/loadPaused.ts @@ -5,11 +5,13 @@ import { ILoader, + isIDeltaManagerFull, LoaderHeader, type IContainer, } from "@fluidframework/container-definitions/internal"; import { IRequest } from "@fluidframework/core-interfaces"; import type { IErrorBase } from "@fluidframework/core-interfaces"; +import { assert } from "@fluidframework/core-utils/internal"; import { GenericError } from "@fluidframework/telemetry-utils/internal"; /* eslint-disable jsdoc/check-indentation */ @@ -63,6 +65,7 @@ export async function loadContainerPaused( const lastProcessedSequenceNumber = dm.initialSequenceNumber; const pauseContainer = (): void => { + assert(isIDeltaManagerFull(dm), "Delta manager does not have inbound/outbound queues."); // eslint-disable-next-line no-void void dm.inbound.pause(); // eslint-disable-next-line no-void diff --git a/packages/runtime/container-runtime-definitions/package.json b/packages/runtime/container-runtime-definitions/package.json index 217058aa776a..f28cb37dab97 100644 --- a/packages/runtime/container-runtime-definitions/package.json +++ b/packages/runtime/container-runtime-definitions/package.json @@ -103,7 +103,14 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_IContainerRuntime": { + "backCompat": false + }, + "Interface_IContainerRuntimeWithResolveHandle_Deprecated": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/runtime/container-runtime-definitions/src/test/types/validateContainerRuntimeDefinitionsPrevious.generated.ts b/packages/runtime/container-runtime-definitions/src/test/types/validateContainerRuntimeDefinitionsPrevious.generated.ts index 078369017175..192f06034e4a 100644 --- a/packages/runtime/container-runtime-definitions/src/test/types/validateContainerRuntimeDefinitionsPrevious.generated.ts +++ b/packages/runtime/container-runtime-definitions/src/test/types/validateContainerRuntimeDefinitionsPrevious.generated.ts @@ -22,6 +22,7 @@ declare type MakeUnusedImportErrorsGoAway = TypeOnly | MinimalType | Fu * typeValidation.broken: * "Interface_IContainerRuntime": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IContainerRuntime = requireAssignableTo, TypeOnly> /* @@ -49,6 +50,7 @@ declare type old_as_current_for_Interface_IContainerRuntimeWithResolveHandle_Dep * typeValidation.broken: * "Interface_IContainerRuntimeWithResolveHandle_Deprecated": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IContainerRuntimeWithResolveHandle_Deprecated = requireAssignableTo, TypeOnly> /* diff --git a/packages/runtime/container-runtime/api-report/container-runtime.legacy.alpha.api.md b/packages/runtime/container-runtime/api-report/container-runtime.legacy.alpha.api.md index eb8c2099ef1a..80d377c4f3e6 100644 --- a/packages/runtime/container-runtime/api-report/container-runtime.legacy.alpha.api.md +++ b/packages/runtime/container-runtime/api-report/container-runtime.legacy.alpha.api.md @@ -67,7 +67,7 @@ export class ContainerRuntime extends TypedEventEmitter; + get deltaManager(): IDeltaManager; // (undocumented) dispose(error?: Error): void; // (undocumented) diff --git a/packages/runtime/container-runtime/package.json b/packages/runtime/container-runtime/package.json index baa9b10635dc..596cd95d8781 100644 --- a/packages/runtime/container-runtime/package.json +++ b/packages/runtime/container-runtime/package.json @@ -231,7 +231,59 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Class_LocalFluidDataStoreContext": { + "backCompat": false + }, + "ClassStatics_LocalFluidDataStoreContext": { + "backCompat": false + }, + "Class_LocalFluidDataStoreContextBase": { + "backCompat": false + }, + "ClassStatics_LocalFluidDataStoreContextBase": { + "backCompat": false + }, + "Class_ChannelCollection": { + "backCompat": false + }, + "ClassStatics_ChannelCollection": { + "backCompat": false + }, + "Class_ContainerRuntime": { + "backCompat": false + }, + "Class_DocumentsSchemaController": { + "forwardCompat": false + }, + "ClassStatics_ContainerRuntime": { + "backCompat": false + }, + "Class_FluidDataStoreContext": { + "backCompat": false + }, + "ClassStatics_FluidDataStoreContext": { + "backCompat": false + }, + "Interface_ISummarizerRuntime": { + "backCompat": false + }, + "Interface_ILocalFluidDataStoreContextProps": { + "backCompat": false + }, + "Interface_IFluidDataStoreContextInternal": { + "backCompat": false + }, + "Interface_IFluidDataStoreContextProps": { + "backCompat": false + }, + "Interface_ILocalDetachedFluidDataStoreContextProps": { + "backCompat": false + }, + "Interface_LoadContainerRuntimeParams": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/runtime/container-runtime/src/connectionTelemetry.ts b/packages/runtime/container-runtime/src/connectionTelemetry.ts index 451c38747fb9..58a9adaed9d2 100644 --- a/packages/runtime/container-runtime/src/connectionTelemetry.ts +++ b/packages/runtime/container-runtime/src/connectionTelemetry.ts @@ -4,7 +4,7 @@ */ import { performance } from "@fluid-internal/client-utils"; -import { IDeltaManager } from "@fluidframework/container-definitions/internal"; +import { IDeltaManagerFull } from "@fluidframework/container-definitions/internal"; import { IContainerRuntimeEvents } from "@fluidframework/container-runtime-definitions/internal"; import { IEventProvider } from "@fluidframework/core-interfaces"; import { assert } from "@fluidframework/core-utils/internal"; @@ -124,7 +124,7 @@ class OpPerfTelemetry { /** * DeltaManager instance to monitor. */ - private readonly deltaManager: IDeltaManager, + private readonly deltaManager: IDeltaManagerFull, /** * Emitter of events for the container runtime. */ @@ -500,7 +500,7 @@ export interface IPerfSignalReport { */ export function ReportOpPerfTelemetry( clientId: string | undefined, - deltaManager: IDeltaManager, + deltaManager: IDeltaManagerFull, containerRuntimeEvents: IEventProvider, logger: ITelemetryLoggerExt, ): void { diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index 576722dcc3f4..d8c2b5cdc203 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -19,6 +19,8 @@ import { IRuntime, LoaderHeader, IDeltaManager, + IDeltaManagerFull, + isIDeltaManagerFull, } from "@fluidframework/container-definitions/internal"; import { IContainerRuntime, @@ -1259,16 +1261,18 @@ export class ContainerRuntime * accesses such as sets "read-only" mode for the summarizer client. This is the default delta manager that should * be used unless the innerDeltaManager is required. */ - public readonly deltaManager: IDeltaManager; + public get deltaManager(): IDeltaManager { + return this._deltaManager; + } + + private readonly _deltaManager: IDeltaManagerFull; + /** * The delta manager provided by the container context. By default, using the default delta manager (proxy) * should be sufficient. This should be used only if necessary. For example, for validating and propagating connected * events which requires access to the actual real only info, this is needed. */ - private readonly innerDeltaManager: IDeltaManager< - ISequencedDocumentMessage, - IDocumentMessage - >; + private readonly innerDeltaManager: IDeltaManagerFull; // internal logger for ContainerRuntime. Use this.logger for stores, summaries, etc. private readonly mc: MonitoringContext; @@ -1528,6 +1532,7 @@ export class ContainerRuntime compressionAlgorithm: CompressionAlgorithms.lz4, }; + assert(isIDeltaManagerFull(deltaManager), "Invalid delta manager"); this.innerDeltaManager = deltaManager; // Here we could wrap/intercept on these functions to block/modify outgoing messages if needed. @@ -1644,7 +1649,7 @@ export class ContainerRuntime this.logger, ); - let outerDeltaManager: IDeltaManager; + let outerDeltaManager: IDeltaManagerFull; this.useDeltaManagerOpsProxy = this.mc.config.getBoolean("Fluid.ContainerRuntime.DeltaManagerOpsProxy") === true; // The summarizerDeltaManager Proxy is used to lie to the summarizer to convince it is in the right state as a summarizer client. @@ -1663,7 +1668,7 @@ export class ContainerRuntime outerDeltaManager = pendingOpsDeltaManagerProxy; } - this.deltaManager = outerDeltaManager; + this._deltaManager = outerDeltaManager; this.handleContext = new ContainerFluidHandleContext("", this); @@ -2034,7 +2039,7 @@ export class ContainerRuntime initialSequenceNumber: this.deltaManager.initialSequenceNumber, }); - ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger); + ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.logger); BindBatchTracker(this, this.logger); this.entryPoint = new LazyPromise(async () => { @@ -2239,8 +2244,8 @@ export class ContainerRuntime }); // If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause // as long as it's not a summarizer client. - if (this.deltaManager.inbound.paused) { - props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry + if (this._deltaManager.inbound.paused) { + props.inboundPaused = this._deltaManager.inbound.paused; // reusing telemetry } const defP = new Deferred(); this.deltaManager.on("op", (message: ISequencedDocumentMessage) => { @@ -3946,7 +3951,7 @@ export class ContainerRuntime ) === true; try { - await this.deltaManager.inbound.pause(); + await this._deltaManager.inbound.pause(); if (shouldPauseInboundSignal) { await this.deltaManager.inboundSignal.pause(); } @@ -4211,7 +4216,7 @@ export class ContainerRuntime this._summarizer?.recordSummaryAttempt?.(summaryRefSeqNum); // Restart the delta manager - this.deltaManager.inbound.resume(); + this._deltaManager.inbound.resume(); if (shouldPauseInboundSignal) { this.deltaManager.inboundSignal.resume(); } diff --git a/packages/runtime/container-runtime/src/deltaManagerProxies.ts b/packages/runtime/container-runtime/src/deltaManagerProxies.ts index 0f717aff1941..0ff85b21b529 100644 --- a/packages/runtime/container-runtime/src/deltaManagerProxies.ts +++ b/packages/runtime/container-runtime/src/deltaManagerProxies.ts @@ -6,8 +6,8 @@ import { TypedEventEmitter } from "@fluid-internal/client-utils"; import type { IConnectionDetails, - IDeltaManager, IDeltaManagerEvents, + IDeltaManagerFull, IDeltaQueue, IDeltaSender, ReadOnlyInfo, @@ -33,7 +33,7 @@ import { summarizerClientType } from "./summary/index.js"; */ export abstract class BaseDeltaManagerProxy extends TypedEventEmitter - implements IDeltaManager + implements IDeltaManagerFull { public get IDeltaSender(): IDeltaSender { return this; @@ -99,12 +99,7 @@ export abstract class BaseDeltaManagerProxy return this.deltaManager.readOnlyInfo; } - constructor( - protected readonly deltaManager: IDeltaManager< - ISequencedDocumentMessage, - IDocumentMessage - >, - ) { + constructor(protected readonly deltaManager: IDeltaManagerFull) { super(); // We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging. @@ -194,12 +189,7 @@ export class DeltaManagerSummarizerProxy extends BaseDeltaManagerProxy { private readonly isSummarizerClient: boolean; - constructor( - protected readonly deltaManager: IDeltaManager< - ISequencedDocumentMessage, - IDocumentMessage - >, - ) { + constructor(protected readonly deltaManager: IDeltaManagerFull) { super(deltaManager); this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType; } @@ -250,10 +240,7 @@ export class DeltaManagerPendingOpsProxy extends BaseDeltaManagerProxy { }; constructor( - protected readonly deltaManager: IDeltaManager< - ISequencedDocumentMessage, - IDocumentMessage - >, + protected readonly deltaManager: IDeltaManagerFull, private readonly pendingStateManager: Pick< PendingStateManager, "minimumPendingMessageSequenceNumber" diff --git a/packages/runtime/container-runtime/src/deltaScheduler.ts b/packages/runtime/container-runtime/src/deltaScheduler.ts index 092fdf206ba6..0bdf853d846b 100644 --- a/packages/runtime/container-runtime/src/deltaScheduler.ts +++ b/packages/runtime/container-runtime/src/deltaScheduler.ts @@ -4,11 +4,8 @@ */ import { performance } from "@fluid-internal/client-utils"; -import { IDeltaManager } from "@fluidframework/container-definitions/internal"; -import { - IDocumentMessage, - ISequencedDocumentMessage, -} from "@fluidframework/driver-definitions/internal"; +import { IDeltaManagerFull } from "@fluidframework/container-definitions/internal"; +import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal"; import { ITelemetryLoggerExt, formatTick } from "@fluidframework/telemetry-utils/internal"; /** @@ -25,7 +22,7 @@ import { ITelemetryLoggerExt, formatTick } from "@fluidframework/telemetry-utils * processed, the time and number of turns it took to process the ops. */ export class DeltaScheduler { - private readonly deltaManager: IDeltaManager; + private readonly deltaManager: IDeltaManagerFull; // The time for processing ops in a single turn. public static readonly processingTime = 50; @@ -53,7 +50,7 @@ export class DeltaScheduler { | undefined; constructor( - deltaManager: IDeltaManager, + deltaManager: IDeltaManagerFull, private readonly logger: ITelemetryLoggerExt, ) { this.deltaManager = deltaManager; diff --git a/packages/runtime/container-runtime/src/scheduleManager.ts b/packages/runtime/container-runtime/src/scheduleManager.ts index 6198674303cc..e8ad6c9b671a 100644 --- a/packages/runtime/container-runtime/src/scheduleManager.ts +++ b/packages/runtime/container-runtime/src/scheduleManager.ts @@ -5,7 +5,7 @@ import type { EventEmitter } from "@fluid-internal/client-utils"; import { performance } from "@fluid-internal/client-utils"; -import { IDeltaManager } from "@fluidframework/container-definitions/internal"; +import { IDeltaManagerFull } from "@fluidframework/container-definitions/internal"; import { assert } from "@fluidframework/core-utils/internal"; import { IDocumentMessage, @@ -43,7 +43,7 @@ export class ScheduleManager { private readonly deltaScheduler: DeltaScheduler; constructor( - private readonly deltaManager: IDeltaManager, + private readonly deltaManager: IDeltaManagerFull, private readonly emitter: EventEmitter, readonly getClientId: () => string | undefined, private readonly logger: ITelemetryLoggerExt, @@ -78,7 +78,7 @@ class ScheduleManagerCore { private batchCount = 0; constructor( - private readonly deltaManager: IDeltaManager, + private readonly deltaManager: IDeltaManagerFull, private readonly getClientId: () => string | undefined, private readonly logger: ITelemetryLoggerExt, ) { diff --git a/packages/runtime/container-runtime/src/test/types/validateContainerRuntimePrevious.generated.ts b/packages/runtime/container-runtime/src/test/types/validateContainerRuntimePrevious.generated.ts index 00512c6b07be..30995d5eef1c 100644 --- a/packages/runtime/container-runtime/src/test/types/validateContainerRuntimePrevious.generated.ts +++ b/packages/runtime/container-runtime/src/test/types/validateContainerRuntimePrevious.generated.ts @@ -31,6 +31,7 @@ declare type old_as_current_for_Class_ContainerRuntime = requireAssignableTo, TypeOnly> /* @@ -85,6 +86,7 @@ declare type current_as_old_for_Class_SummaryCollection = requireAssignableTo, TypeOnly> /* @@ -859,6 +861,7 @@ declare type old_as_current_for_Interface_ISummarizerRuntime = requireAssignable * typeValidation.broken: * "Interface_ISummarizerRuntime": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_ISummarizerRuntime = requireAssignableTo, TypeOnly> /* @@ -1093,6 +1096,7 @@ declare type old_as_current_for_Interface_LoadContainerRuntimeParams = requireAs * typeValidation.broken: * "Interface_LoadContainerRuntimeParams": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_LoadContainerRuntimeParams = requireAssignableTo, TypeOnly> /* diff --git a/packages/runtime/datastore/package.json b/packages/runtime/datastore/package.json index 562e34959121..8024a2c645ff 100644 --- a/packages/runtime/datastore/package.json +++ b/packages/runtime/datastore/package.json @@ -160,7 +160,15 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Class_FluidDataStoreRuntime": { + "backCompat": false + }, + "ClassStatics_FluidDataStoreRuntime": { + "backCompat": false, + "forwardCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/runtime/datastore/src/test/types/validateDatastorePrevious.generated.ts b/packages/runtime/datastore/src/test/types/validateDatastorePrevious.generated.ts index bab8d7182452..1e149592219a 100644 --- a/packages/runtime/datastore/src/test/types/validateDatastorePrevious.generated.ts +++ b/packages/runtime/datastore/src/test/types/validateDatastorePrevious.generated.ts @@ -31,6 +31,7 @@ declare type old_as_current_for_Class_FluidDataStoreRuntime = requireAssignableT * typeValidation.broken: * "Class_FluidDataStoreRuntime": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Class_FluidDataStoreRuntime = requireAssignableTo, TypeOnly> /* @@ -58,6 +59,7 @@ declare type current_as_old_for_Class_FluidObjectHandle = requireAssignableTo, TypeOnly> /* diff --git a/packages/runtime/runtime-definitions/package.json b/packages/runtime/runtime-definitions/package.json index 958e745d7a6f..3f5391f027ff 100644 --- a/packages/runtime/runtime-definitions/package.json +++ b/packages/runtime/runtime-definitions/package.json @@ -111,7 +111,17 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_IFluidDataStoreContext": { + "backCompat": false + }, + "Interface_IFluidDataStoreContextDetached": { + "backCompat": false + }, + "Interface_IFluidParentContext": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/runtime/runtime-definitions/src/test/types/validateRuntimeDefinitionsPrevious.generated.ts b/packages/runtime/runtime-definitions/src/test/types/validateRuntimeDefinitionsPrevious.generated.ts index d4b13e2a2af8..8d8ca17ec947 100644 --- a/packages/runtime/runtime-definitions/src/test/types/validateRuntimeDefinitionsPrevious.generated.ts +++ b/packages/runtime/runtime-definitions/src/test/types/validateRuntimeDefinitionsPrevious.generated.ts @@ -211,6 +211,7 @@ declare type old_as_current_for_Interface_IFluidDataStoreContext = requireAssign * typeValidation.broken: * "Interface_IFluidDataStoreContext": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IFluidDataStoreContext = requireAssignableTo, TypeOnly> /* @@ -229,6 +230,7 @@ declare type old_as_current_for_Interface_IFluidDataStoreContextDetached = requi * typeValidation.broken: * "Interface_IFluidDataStoreContextDetached": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IFluidDataStoreContextDetached = requireAssignableTo, TypeOnly> /* @@ -283,6 +285,7 @@ declare type old_as_current_for_Interface_IFluidParentContext = requireAssignabl * typeValidation.broken: * "Interface_IFluidParentContext": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IFluidParentContext = requireAssignableTo, TypeOnly> /* diff --git a/packages/runtime/runtime-utils/src/index.ts b/packages/runtime/runtime-utils/src/index.ts index 051d809204a0..ae9272924b59 100644 --- a/packages/runtime/runtime-utils/src/index.ts +++ b/packages/runtime/runtime-utils/src/index.ts @@ -47,4 +47,7 @@ export { export { unpackChildNodesUsedRoutes } from "./unpackUsedRoutes.js"; export { ReadAndParseBlob, seqFromTree, encodeCompactIdToString } from "./utils.js"; export { isSnapshotFetchRequiredForLoadingGroupId } from "./snapshotUtils.js"; -export { toDeltaManagerErased, toDeltaManagerInternal } from "./deltaManager.js"; +export { + toDeltaManagerErased, + toDeltaManagerInternal, +} from "./deltaManager.js"; diff --git a/packages/runtime/test-runtime-utils/package.json b/packages/runtime/test-runtime-utils/package.json index d1cc3be4c93e..420f56b9fcc7 100644 --- a/packages/runtime/test-runtime-utils/package.json +++ b/packages/runtime/test-runtime-utils/package.json @@ -157,7 +157,14 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Class_MockFluidDataStoreContext": { + "backCompat": false + }, + "ClassStatics_MockFluidDataStoreContext": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/runtime/test-runtime-utils/src/test/types/validateTestRuntimeUtilsPrevious.generated.ts b/packages/runtime/test-runtime-utils/src/test/types/validateTestRuntimeUtilsPrevious.generated.ts index bb782e3a2aa2..d6f765fb97e6 100644 --- a/packages/runtime/test-runtime-utils/src/test/types/validateTestRuntimeUtilsPrevious.generated.ts +++ b/packages/runtime/test-runtime-utils/src/test/types/validateTestRuntimeUtilsPrevious.generated.ts @@ -175,6 +175,7 @@ declare type old_as_current_for_Class_MockFluidDataStoreContext = requireAssigna * typeValidation.broken: * "Class_MockFluidDataStoreContext": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Class_MockFluidDataStoreContext = requireAssignableTo, TypeOnly> /* @@ -364,6 +365,7 @@ declare type current_as_old_for_ClassStatics_MockDeltaQueue = requireAssignableT * typeValidation.broken: * "ClassStatics_MockFluidDataStoreContext": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_ClassStatics_MockFluidDataStoreContext = requireAssignableTo, TypeOnly> /* diff --git a/packages/test/local-server-tests/src/test/opsOnReconnect.spec.ts b/packages/test/local-server-tests/src/test/opsOnReconnect.spec.ts index 203b55a819b5..b88ffee67ac5 100644 --- a/packages/test/local-server-tests/src/test/opsOnReconnect.spec.ts +++ b/packages/test/local-server-tests/src/test/opsOnReconnect.spec.ts @@ -36,6 +36,7 @@ import { LoaderContainerTracker, LocalCodeLoader, TestFluidObjectFactory, + toIDeltaManagerFull, createAndAttachContainer, waitForContainerConnection, } from "@fluidframework/test-utils/internal"; @@ -654,7 +655,7 @@ describe("Ops on Reconnect", () => { // At this point, the delta manager should have the messages // in its buffer but not in its outbound queue, // as ops have not been flushed yet - assert.strictEqual(container1.deltaManager.outbound.length, 0); + assert.strictEqual(toIDeltaManagerFull(container1.deltaManager).outbound.length, 0); assert.deepStrictEqual(receivedValues, [], "Values have been sent unexpectedly"); // Wait for the Container to get reconnected. diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/opCriticalPath.time.spec.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/opCriticalPath.time.spec.ts index 9e54b84e46ed..cce7fc9dae47 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/opCriticalPath.time.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/opCriticalPath.time.spec.ts @@ -13,6 +13,7 @@ import { DefaultSummaryConfiguration, } from "@fluidframework/container-runtime/internal"; import { + toIDeltaManagerFull, ITestContainerConfig, ITestObjectProvider, timeoutPromise, @@ -72,7 +73,7 @@ describeCompat( sendOps("A"); const opsSent = await timeoutPromise( (resolve) => { - containerRuntime.deltaManager.outbound.once("idle", resolve); + toIDeltaManagerFull(containerRuntime.deltaManager).outbound.once("idle", resolve); }, { errorMsg: "container2 outbound queue never reached idle state" }, ); diff --git a/packages/test/test-end-to-end-tests/src/test/containerDirtyFlag.spec.ts b/packages/test/test-end-to-end-tests/src/test/containerDirtyFlag.spec.ts index 3e3e5d251582..c3a5044a1045 100644 --- a/packages/test/test-end-to-end-tests/src/test/containerDirtyFlag.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/containerDirtyFlag.spec.ts @@ -17,6 +17,7 @@ import { ITestContainerConfig, ITestFluidObject, ITestObjectProvider, + toIDeltaManagerFull, createAndAttachContainer, waitForContainerConnection, } from "@fluidframework/test-utils/internal"; @@ -63,7 +64,10 @@ describeCompat("Container dirty flag", "NoCompat", (getTestObjectProvider, apis) await args.ensureSynchronized(); await args.opProcessingController.pauseProcessing(container); - assert(toDeltaManagerInternal(dataStore.runtime.deltaManager).outbound.paused); + const deltaManagerFull = toIDeltaManagerFull( + toDeltaManagerInternal(dataStore.runtime.deltaManager), + ); + assert(deltaManagerFull.outbound.paused); await cb(container, dataStore, map); diff --git a/packages/test/test-end-to-end-tests/src/test/data-virtualization/loadNewerGroupIdSnapshot.spec.ts b/packages/test/test-end-to-end-tests/src/test/data-virtualization/loadNewerGroupIdSnapshot.spec.ts index 7414a3e5e4ab..b08c54e7218d 100644 --- a/packages/test/test-end-to-end-tests/src/test/data-virtualization/loadNewerGroupIdSnapshot.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/data-virtualization/loadNewerGroupIdSnapshot.spec.ts @@ -26,6 +26,7 @@ import type { ISnapshot, ISnapshotTree } from "@fluidframework/driver-definition import { MockLogger } from "@fluidframework/telemetry-utils/internal"; import { type ITestObjectProvider, + toIDeltaManagerFull, createSummarizerFromFactory, summarizeNow, } from "@fluidframework/test-utils/internal"; @@ -439,7 +440,7 @@ describeCompat( await provider.ensureSynchronized(); // Pause the summarizer2 so we can generate a summary in the future // Note: The summarizing containers don't get added to the loader container tracker, so we manually pause here - await container2.deltaManager.inbound.pause(); + await toIDeltaManagerFull(container2.deltaManager).inbound.pause(); // Send an op dataObjectA._root.set("C", "C"); diff --git a/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts b/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts index 768ecd76fcc7..a08eb931de89 100644 --- a/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts @@ -41,6 +41,7 @@ import { LocalCodeLoader, SupportedExportInterfaces, TestFluidObjectFactory, + toIDeltaManagerFull, getContainerEntryPointBackCompat, getDataStoreEntryPointBackCompat, timeoutPromise, @@ -115,7 +116,7 @@ describeCompat("Detached Container", "FullCompat", (getTestObjectProvider, apis) ); assert.strictEqual(container.closed, false, "Container should be open"); assert.strictEqual( - container.deltaManager.inbound.length, + toIDeltaManagerFull(container.deltaManager).inbound.length, 0, "Inbound queue should be empty", ); @@ -156,7 +157,7 @@ describeCompat("Detached Container", "FullCompat", (getTestObjectProvider, apis) ); assert.strictEqual(container.closed, false, "Container should be open"); assert.strictEqual( - container.deltaManager.inbound.length, + toIDeltaManagerFull(container.deltaManager).inbound.length, 0, "Inbound queue should be empty", ); @@ -931,7 +932,7 @@ describeCompat("Detached Container", "NoCompat", (getTestObjectProvider, apis) = ); assert.strictEqual(container.closed, false, "Container should be open"); assert.strictEqual( - container.deltaManager.inbound.length, + toIDeltaManagerFull(container.deltaManager).inbound.length, 0, "Inbound queue should be empty", ); diff --git a/packages/test/test-end-to-end-tests/src/test/directoryEndToEndTests.spec.ts b/packages/test/test-end-to-end-tests/src/test/directoryEndToEndTests.spec.ts index 472995368fda..1e6512f4a33f 100644 --- a/packages/test/test-end-to-end-tests/src/test/directoryEndToEndTests.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/directoryEndToEndTests.spec.ts @@ -26,6 +26,7 @@ import { ITestContainerConfig, ITestFluidObject, ITestObjectProvider, + toIDeltaManagerFull, getContainerEntryPointBackCompat, } from "@fluidframework/test-utils/internal"; @@ -1304,18 +1305,18 @@ describeCompat( } async function pauseAllContainers() { - await container1.deltaManager.inbound.pause(); - await container2.deltaManager.inbound.pause(); - await container3.deltaManager.inbound.pause(); + await toIDeltaManagerFull(container1.deltaManager).inbound.pause(); + await toIDeltaManagerFull(container2.deltaManager).inbound.pause(); + await toIDeltaManagerFull(container3.deltaManager).inbound.pause(); - await container1.deltaManager.outbound.pause(); - await container2.deltaManager.outbound.pause(); - await container3.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container1.deltaManager).outbound.pause(); + await toIDeltaManagerFull(container2.deltaManager).outbound.pause(); + await toIDeltaManagerFull(container3.deltaManager).outbound.pause(); } function resumeContainer(c: IContainer) { - c.deltaManager.inbound.resume(); - c.deltaManager.outbound.resume(); + toIDeltaManagerFull(c.deltaManager).inbound.resume(); + toIDeltaManagerFull(c.deltaManager).outbound.resume(); } /** diff --git a/packages/test/test-end-to-end-tests/src/test/fewerBatches.spec.ts b/packages/test/test-end-to-end-tests/src/test/fewerBatches.spec.ts index 7cce237a323d..c7ff88478c1d 100644 --- a/packages/test/test-end-to-end-tests/src/test/fewerBatches.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/fewerBatches.spec.ts @@ -18,6 +18,7 @@ import { FlushModeExperimental, } from "@fluidframework/runtime-definitions/internal"; import { + toIDeltaManagerFull, ChannelFactoryRegistry, DataObjectFactoryType, ITestContainerConfig, @@ -86,9 +87,12 @@ describeCompat("Fewer batches", "NoCompat", (getTestObjectProvider, apis) => { await waitForContainerConnection(localContainer); await waitForContainerConnection(remoteContainer); - localContainer.deltaManager.outbound.on("op", (batch: IDocumentMessage[]) => { - capturedBatches.push(batch); - }); + toIDeltaManagerFull(localContainer.deltaManager).outbound.on( + "op", + (batch: IDocumentMessage[]) => { + capturedBatches.push(batch); + }, + ); await provider.ensureSynchronized(); }; diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts index a619fc4fb45d..69920693332e 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts @@ -35,6 +35,7 @@ import { toFluidHandleInternal } from "@fluidframework/runtime-utils/internal"; import { ITestContainerConfig, ITestObjectProvider, + toIDeltaManagerFull, createSummarizer, createTestConfigProvider, summarizeNow, @@ -1159,7 +1160,7 @@ describeCompat("GC attachment blob sweep tests", "NoCompat", (getTestObjectProvi // Pause the inbound queue so that GC ops are not processed in between failures. This will be resumed // before the final attempt. if (blockInboundGCOp) { - await containerRuntime.deltaManager.inbound.pause(); + await toIDeltaManagerFull(containerRuntime.deltaManager).inbound.pause(); } let summarizeFunc = containerRuntime.summarize; @@ -1175,7 +1176,7 @@ describeCompat("GC attachment blob sweep tests", "NoCompat", (getTestObjectProvi } // If this is the last attempt, resume the inbound queue to let the GC ops (if any) through. if (blockInboundGCOp) { - containerRuntime.deltaManager.inbound.resume(); + toIDeltaManagerFull(containerRuntime.deltaManager).inbound.resume(); } return results; }; diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts index 142618dd5f48..05c7e79eaaa2 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts @@ -42,6 +42,7 @@ import { import { ITestContainerConfig, ITestObjectProvider, + toIDeltaManagerFull, createSummarizer, createTestConfigProvider, getContainerEntryPointBackCompat, @@ -781,7 +782,7 @@ describeCompat("GC data store sweep tests", "NoCompat", (getTestObjectProvider) // Pause the inbound queue so that GC ops are not processed in between failures. This will be resumed // before the final attempt. if (blockInboundGCOp) { - await containerRuntime.deltaManager.inbound.pause(); + await toIDeltaManagerFull(containerRuntime.deltaManager).inbound.pause(); } let summarizeFunc = containerRuntime.summarize; @@ -797,7 +798,7 @@ describeCompat("GC data store sweep tests", "NoCompat", (getTestObjectProvider) } // If this is the last attempt, resume the inbound queue to let the GC ops (if any) through. if (blockInboundGCOp) { - containerRuntime.deltaManager.inbound.resume(); + toIDeltaManagerFull(containerRuntime.deltaManager).inbound.resume(); } return results; }; diff --git a/packages/test/test-end-to-end-tests/src/test/intervalCollectionEndToEndTests.spec.ts b/packages/test/test-end-to-end-tests/src/test/intervalCollectionEndToEndTests.spec.ts index a5929287701f..efe4420cf547 100644 --- a/packages/test/test-end-to-end-tests/src/test/intervalCollectionEndToEndTests.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/intervalCollectionEndToEndTests.spec.ts @@ -22,6 +22,7 @@ import { ITestContainerConfig, ITestFluidObject, ITestObjectProvider, + toIDeltaManagerFull, getContainerEntryPointBackCompat, waitForContainerConnection, } from "@fluidframework/test-utils/internal"; @@ -132,7 +133,10 @@ describeCompat( await provider.ensureSynchronized(); await provider.opProcessingController.pauseProcessing(container); - assert(toDeltaManagerInternal(dataStore.runtime.deltaManager).outbound.paused); + const deltaManagerFull = toIDeltaManagerFull( + toDeltaManagerInternal(dataStore.runtime.deltaManager), + ); + assert(deltaManagerFull.outbound.paused); // the "callback" portion of the original e2e test const sharedString = await dataStore.getSharedObject(stringId); diff --git a/packages/test/test-end-to-end-tests/src/test/messageSize.spec.ts b/packages/test/test-end-to-end-tests/src/test/messageSize.spec.ts index b1b78576c46f..08094501a6b8 100644 --- a/packages/test/test-end-to-end-tests/src/test/messageSize.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/messageSize.spec.ts @@ -23,6 +23,7 @@ import type { ISharedMap } from "@fluidframework/map/internal"; import { FlushMode } from "@fluidframework/runtime-definitions/internal"; import { GenericError } from "@fluidframework/telemetry-utils/internal"; import { + toIDeltaManagerFull, ChannelFactoryRegistry, DataObjectFactoryType, ITestContainerConfig, @@ -447,7 +448,7 @@ describeCompat("Message size", "NoCompat", (getTestObjectProvider, apis) => { }); totalPayloadSizeInBytes = 0; totalOps = 0; - localContainer.deltaManager.outbound.on("push", (messages) => { + toIDeltaManagerFull(localContainer.deltaManager).outbound.on("push", (messages) => { totalPayloadSizeInBytes += JSON.stringify(messages).length; totalOps += messages.length; }); @@ -623,13 +624,13 @@ describeCompat("Message size", "NoCompat", (getTestObjectProvider, apis) => { container.disconnect(); container.once("connected", () => { resolve(); - container.deltaManager.outbound.off("op", handler); + toIDeltaManagerFull(container.deltaManager).outbound.off("op", handler); }); container.connect(); } }; - container.deltaManager.outbound.on("op", handler); + toIDeltaManagerFull(container.deltaManager).outbound.on("op", handler); }); }; diff --git a/packages/test/test-end-to-end-tests/src/test/migration-shim/reconnect.spec.ts b/packages/test/test-end-to-end-tests/src/test/migration-shim/reconnect.spec.ts index d31fe4e908c9..e7cff7c15ca3 100644 --- a/packages/test/test-end-to-end-tests/src/test/migration-shim/reconnect.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/migration-shim/reconnect.spec.ts @@ -26,6 +26,7 @@ import { type ConfigTypes, type IConfigProviderBase } from "@fluidframework/core import { type IChannel } from "@fluidframework/datastore-definitions/internal"; import { type ITestObjectProvider, + toIDeltaManagerFull, createSummarizerFromFactory, summarizeNow, waitForContainerConnection, @@ -330,7 +331,7 @@ describeCompat("Stamped v2 ops", "NoCompat", (getTestObjectProvider, apis) => { // generate stashed ops await provider.opProcessingController.pauseProcessing(container1); - await container1.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container1.deltaManager).outbound.pause(); node1.quantity = 1; node1.quantity = 2; node1.quantity = 3; @@ -392,7 +393,7 @@ describeCompat("Stamped v2 ops", "NoCompat", (getTestObjectProvider, apis) => { // generate stashed ops await provider.opProcessingController.pauseProcessing(container2); - await container2.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container2.deltaManager).outbound.pause(); node2.quantity = 1; node2.quantity = 2; node2.quantity = 3; @@ -431,7 +432,7 @@ describeCompat("Stamped v2 ops", "NoCompat", (getTestObjectProvider, apis) => { // generate stashed ops with a migration occurring await provider.opProcessingController.pauseProcessing(container1); - await container1.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container1.deltaManager).outbound.pause(); shim1.submitMigrateOp(); updateQuantity(legacyTree1, 1); @@ -499,7 +500,7 @@ describeCompat("Stamped v2 ops", "NoCompat", (getTestObjectProvider, apis) => { // generate stashed ops with a migration occurring await provider.opProcessingController.pauseProcessing(container1); - await container1.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container1.deltaManager).outbound.pause(); shim1.submitMigrateOp(); const pendingState = await container1.closeAndGetPendingLocalState?.(); diff --git a/packages/test/test-end-to-end-tests/src/test/opReentrancy.spec.ts b/packages/test/test-end-to-end-tests/src/test/opReentrancy.spec.ts index 297067545284..336c0b4aab0c 100644 --- a/packages/test/test-end-to-end-tests/src/test/opReentrancy.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/opReentrancy.spec.ts @@ -18,6 +18,7 @@ import { ITestContainerConfig, ITestFluidObject, ITestObjectProvider, + toIDeltaManagerFull, getContainerEntryPointBackCompat, } from "@fluidframework/test-utils/internal"; @@ -274,8 +275,9 @@ describeCompat( runtimeOptions: {}, }); - await container1.deltaManager.inbound.pause(); - await container1.deltaManager.outbound.pause(); + const container1DeltaManager = toIDeltaManagerFull(container1.deltaManager); + await container1DeltaManager.inbound.pause(); + await container1DeltaManager.outbound.pause(); sharedMap1.on("valueChanged", (changed) => { if (changed.key !== "key2") { @@ -285,8 +287,8 @@ describeCompat( sharedMap1.set("key1", "1"); - container1.deltaManager.inbound.resume(); - container1.deltaManager.outbound.resume(); + container1DeltaManager.inbound.resume(); + container1DeltaManager.outbound.resume(); await provider.ensureSynchronized(); @@ -356,8 +358,9 @@ describeCompat( await setupContainers(testConfig.options, testConfig.featureGates); - await container1.deltaManager.inbound.pause(); - await container1.deltaManager.outbound.pause(); + const deltaManagerFull = toIDeltaManagerFull(container1.deltaManager); + await deltaManagerFull.inbound.pause(); + await deltaManagerFull.outbound.pause(); sharedMap1.on("valueChanged", (changed) => { if (changed.key !== "key2") { @@ -372,8 +375,8 @@ describeCompat( sharedMap1.set("key1", "1"); - container1.deltaManager.inbound.resume(); - container1.deltaManager.outbound.resume(); + deltaManagerFull.inbound.resume(); + deltaManagerFull.outbound.resume(); await provider.ensureSynchronized(); // The offending container is not closed diff --git a/packages/test/test-end-to-end-tests/src/test/stashedOps.spec.ts b/packages/test/test-end-to-end-tests/src/test/stashedOps.spec.ts index 5c689e19bbc4..fcf58276fea1 100644 --- a/packages/test/test-end-to-end-tests/src/test/stashedOps.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/stashedOps.spec.ts @@ -63,6 +63,7 @@ import { timeoutPromise, waitForContainerConnection, timeoutAwait, + toIDeltaManagerFull, } from "@fluidframework/test-utils/internal"; import { SchemaFactory, ITree, TreeViewConfiguration } from "@fluidframework/tree"; import { SharedTree } from "@fluidframework/tree/internal"; @@ -114,7 +115,10 @@ const getPendingOps = async ( await testObjectProvider.ensureSynchronized(); await testObjectProvider.opProcessingController.pauseProcessing(container); - assert(toDeltaManagerInternal(dataStore.runtime.deltaManager).outbound.paused); + const deltaManagerInternal = toIDeltaManagerFull( + toDeltaManagerInternal(dataStore.runtime.deltaManager), + ); + assert(deltaManagerInternal.outbound.paused); await cb(container, dataStore); @@ -1276,7 +1280,10 @@ describeCompat("stashed ops", "NoCompat", (getTestObjectProvider, apis) => { assert.ok(serializedClientId); await provider.opProcessingController.pauseProcessing(container); - assert(toDeltaManagerInternal(dataStore.runtime.deltaManager).outbound.paused); + const deltaManagerFull = toIDeltaManagerFull( + toDeltaManagerInternal(dataStore.runtime.deltaManager), + ); + assert(deltaManagerFull.outbound.paused); [...Array(lots).keys()].map((i) => dataStore.root.set(`test op #${i}`, i)); @@ -1479,7 +1486,10 @@ describeCompat("stashed ops", "NoCompat", (getTestObjectProvider, apis) => { ); await provider.opProcessingController.pauseProcessing(container2); - assert(toDeltaManagerInternal(dataStore2.runtime.deltaManager).outbound.paused); + const deltaManagerFull = toIDeltaManagerFull( + toDeltaManagerInternal(dataStore2.runtime.deltaManager), + ); + assert(deltaManagerFull.outbound.paused); [...Array(lots).keys()].map((i) => map2.set((i + lots).toString(), i + lots)); const morePendingOps = await container2.getPendingLocalState?.(); @@ -1931,7 +1941,7 @@ describeCompat("stashed ops", "NoCompat", (getTestObjectProvider, apis) => { )) as IContainerExperimental; // pause outgoing ops so we can detect dropped stashed changes - await container.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container.deltaManager).outbound.pause(); let pendingState: string | undefined; let pendingStateP; const dataStore = (await container.getEntryPoint()) as ITestFluidObject; @@ -2233,7 +2243,7 @@ describeCompat( }, pendingLocalState, ); - await container.deltaManager.outbound.pause(); + await toIDeltaManagerFull(container.deltaManager).outbound.pause(); container.connect(); // Wait for the container to connect, and then pause the inbound queue @@ -2242,7 +2252,7 @@ describeCompat( reject: true, errorMsg: `${loggingId} didn't connect in time`, }); - await container.deltaManager.inbound.pause(); + await toIDeltaManagerFull(container.deltaManager).inbound.pause(); // Now this container should submit the op when we resume the outbound queue return container; @@ -2258,27 +2268,29 @@ describeCompat( const dataStore3 = (await container3.getEntryPoint()) as ITestFluidObject; const counter3 = await dataStore3.getSharedObject(counterId); + const container2DeltaManager = toIDeltaManagerFull(container2.deltaManager); + const container3DeltaManager = toIDeltaManagerFull(container3.deltaManager); // Here's the "in parallel" part - resume both outbound queues at the same time, // and then resume both inbound queues once the outbound queues are idle (done sending). const allSentP = Promise.all([ timeoutPromise( (resolve) => { - container2.deltaManager.outbound.once("idle", resolve); + container2DeltaManager.outbound.once("idle", resolve); }, { errorMsg: "container2 outbound queue never reached idle state" }, ), timeoutPromise( (resolve) => { - container3.deltaManager.outbound.once("idle", resolve); + container3DeltaManager.outbound.once("idle", resolve); }, { errorMsg: "container3 outbound queue never reached idle state" }, ), ]); - container2.deltaManager.outbound.resume(); - container3.deltaManager.outbound.resume(); + container2DeltaManager.outbound.resume(); + container3DeltaManager.outbound.resume(); await allSentP; - container2.deltaManager.inbound.resume(); - container3.deltaManager.inbound.resume(); + container2DeltaManager.inbound.resume(); + container3DeltaManager.inbound.resume(); // At this point, both rehydrated containers should have submitted the same Counter op. // ContainerRuntime will use PSM and BatchTracker and it will play out like this: diff --git a/packages/test/test-end-to-end-tests/src/test/t9sregressiontest.spec.ts b/packages/test/test-end-to-end-tests/src/test/t9sregressiontest.spec.ts index 65a9bbdaf2d4..79d37131c33c 100644 --- a/packages/test/test-end-to-end-tests/src/test/t9sregressiontest.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/t9sregressiontest.spec.ts @@ -13,6 +13,7 @@ import { DataObjectFactoryType, ITestContainerConfig, ITestFluidObject, + toIDeltaManagerFull, createAndAttachContainer, } from "@fluidframework/test-utils/internal"; @@ -54,7 +55,10 @@ describeCompat("t9s issue regression test", "NoCompat", (getTestObjectProvider, [...Array(60).keys()].map((i) => map2.set(`test op ${i}`, i)); await provider.ensureSynchronized(); await provider.opProcessingController.pauseProcessing(container2); - assert(toDeltaManagerInternal(dataStore2.runtime.deltaManager).outbound.paused); + const deltaManagerFull = toIDeltaManagerFull( + toDeltaManagerInternal(dataStore2.runtime.deltaManager), + ); + assert(deltaManagerFull.outbound.paused); map2.set("a key", "a value"); await provider.ensureSynchronized(); diff --git a/packages/test/test-utils/package.json b/packages/test/test-utils/package.json index a8f19e0c8286..b57189eebc81 100644 --- a/packages/test/test-utils/package.json +++ b/packages/test/test-utils/package.json @@ -167,7 +167,20 @@ "typescript": "~5.4.5" }, "typeValidation": { - "broken": {}, + "broken": { + "Class_TestFluidObject": { + "backCompat": false + }, + "ClassStatics_TestFluidObject": { + "backCompat": false + }, + "Interface_ITestFluidObject": { + "backCompat": false + }, + "Interface_IProvideTestFluidObject": { + "backCompat": false + } + }, "entrypoint": "legacy" } } diff --git a/packages/test/test-utils/src/containerUtils.ts b/packages/test/test-utils/src/containerUtils.ts index 0d34463f7fe3..303d0aaaa0da 100644 --- a/packages/test/test-utils/src/containerUtils.ts +++ b/packages/test/test-utils/src/containerUtils.ts @@ -3,10 +3,19 @@ * Licensed under the MIT License. */ -import { IContainer } from "@fluidframework/container-definitions/internal"; +import { + IContainer, + IDeltaManager, + type IDeltaManagerFull, +} from "@fluidframework/container-definitions/internal"; import { ConnectionState } from "@fluidframework/container-loader"; import { IResponse } from "@fluidframework/core-interfaces"; import { assert } from "@fluidframework/core-utils/internal"; +import type { IDeltaManagerErased } from "@fluidframework/datastore-definitions/internal"; +import type { + IDocumentMessage, + ISequencedDocumentMessage, +} from "@fluidframework/driver-definitions/internal"; import { IDataStore } from "@fluidframework/runtime-definitions/internal"; import { PromiseExecutor, TimeoutWithError, timeoutPromise } from "./timeoutUtils.js"; @@ -89,3 +98,20 @@ export async function getDataStoreEntryPointBackCompat(dataStore: IDataStore) assert(response.status === 200, "empty request should return data object"); return response.value as T; } + +/** + * @internal + */ +export function toIDeltaManagerFull( + deltaManager: + | IDeltaManager + | IDeltaManagerErased, +): IDeltaManagerFull { + assert( + "inbound" in deltaManager && "outbound" in deltaManager, + "Delta manager does not have inbound/outbound queues.", + ); + return deltaManager as unknown as + | IDeltaManagerErased + | IDeltaManager as IDeltaManagerFull; +} diff --git a/packages/test/test-utils/src/index.ts b/packages/test/test-utils/src/index.ts index 06313883301f..e479866fc9d5 100644 --- a/packages/test/test-utils/src/index.ts +++ b/packages/test/test-utils/src/index.ts @@ -56,6 +56,7 @@ export { type TimeoutWithValue, } from "./timeoutUtils.js"; export { + toIDeltaManagerFull, waitForContainerConnection, getContainerEntryPointBackCompat, getDataStoreEntryPointBackCompat, diff --git a/packages/test/test-utils/src/loaderContainerTracker.ts b/packages/test/test-utils/src/loaderContainerTracker.ts index a48956d6882c..42ad813fd86e 100644 --- a/packages/test/test-utils/src/loaderContainerTracker.ts +++ b/packages/test/test-utils/src/loaderContainerTracker.ts @@ -22,7 +22,7 @@ import { } from "@fluidframework/driver-definitions/internal"; import { canBeCoalescedByService } from "@fluidframework/driver-utils/internal"; -import { waitForContainerConnection } from "./containerUtils.js"; +import { toIDeltaManagerFull, waitForContainerConnection } from "./containerUtils.js"; import { debug } from "./debug.js"; import { IOpProcessingController } from "./testObjectProvider.js"; import { timeoutAwait, timeoutPromise } from "./timeoutUtils.js"; @@ -145,7 +145,8 @@ export class LoaderContainerTracker implements IOpProcessingController { * @param record - the record to update the trailing op information */ private trackTrailingNoOps(container: IContainer, record: ContainerRecord) { - container.deltaManager.outbound.on("op", (messages) => { + const deltaManagerFull = toIDeltaManagerFull(container.deltaManager); + deltaManagerFull.outbound.on("op", (messages) => { for (const msg of messages) { if (canBeCoalescedByService(msg)) { // Track the NoOp that was sent. @@ -161,7 +162,7 @@ export class LoaderContainerTracker implements IOpProcessingController { } }); - container.deltaManager.inbound.on("push", (message) => { + deltaManagerFull.inbound.on("push", (message) => { // Received the no op back, update the record if we are tracking if ( canBeCoalescedByService(message) && @@ -458,12 +459,12 @@ export class LoaderContainerTracker implements IOpProcessingController { return new Promise((resolve) => { const handler = () => { containersToApply.map((c) => { - c.deltaManager.inbound.off("push", handler); + toIDeltaManagerFull(c.deltaManager).inbound.off("push", handler); }); resolve(); }; containersToApply.map((c) => { - c.deltaManager.inbound.on("push", handler); + toIDeltaManagerFull(c.deltaManager).inbound.on("push", handler); }); }); } @@ -482,8 +483,9 @@ export class LoaderContainerTracker implements IOpProcessingController { ); if (record?.paused === true) { debugWait(`${record.index}: container resumed`); - container.deltaManager.inbound.resume(); - container.deltaManager.outbound.resume(); + const deltaManagerFull = toIDeltaManagerFull(container.deltaManager); + deltaManagerFull.inbound.resume(); + deltaManagerFull.outbound.resume(); resumed.push(container); record.paused = false; } @@ -526,12 +528,13 @@ export class LoaderContainerTracker implements IOpProcessingController { */ private async pauseContainer(container: IContainer, record: ContainerRecord) { debugWait(`${record.index}: pausing container`); - assert(!container.deltaManager.outbound.paused, "Container should not be paused yet"); - assert(!container.deltaManager.inbound.paused, "Container should not be paused yet"); + const deltaManagerFull = toIDeltaManagerFull(container.deltaManager); + assert(!deltaManagerFull.outbound.paused, "Container should not be paused yet"); + assert(!deltaManagerFull.inbound.paused, "Container should not be paused yet"); // Pause outbound debugWait(`${record.index}: pausing container outbound queues`); - await container.deltaManager.outbound.pause(); + await deltaManagerFull.outbound.pause(); // Ensure the container is connected first. if (container.connectionState !== ConnectionState.Connected) { @@ -542,7 +545,7 @@ export class LoaderContainerTracker implements IOpProcessingController { // Check if the container is in write mode if (!container.deltaManager.active) { let proposalP: Promise | undefined; - if (container.deltaManager.outbound.idle) { + if (deltaManagerFull.outbound.idle) { // Need to generate an op to force write mode debugWait(`${record.index}: container force write connection`); const maybeContainer = container as Partial; @@ -556,11 +559,11 @@ export class LoaderContainerTracker implements IOpProcessingController { // Wait for nack debugWait(`${record.index}: Wait for container disconnect`); - container.deltaManager.outbound.resume(); + deltaManagerFull.outbound.resume(); await new Promise((resolve) => container.once("disconnected", resolve)); const accepted = proposalP ? await proposalP : false; assert(!accepted, "A proposal in read mode should be rejected"); - await container.deltaManager.outbound.pause(); + await deltaManagerFull.outbound.pause(); // Ensure the container is reconnect. if (container.connectionState !== ConnectionState.Connected) { @@ -572,7 +575,7 @@ export class LoaderContainerTracker implements IOpProcessingController { debugWait(`${record.index}: pausing container inbound queues`); // Pause inbound - await container.deltaManager.inbound.pause(); + await deltaManagerFull.inbound.pause(); debugWait(`${record.index}: container paused`); @@ -588,7 +591,10 @@ export class LoaderContainerTracker implements IOpProcessingController { * Pausing will switch the container to write mode. See `pauseProcessing` */ public async processIncoming(...containers: IContainer[]) { - return this.processQueue(containers, (container) => container.deltaManager.inbound); + return this.processQueue( + containers, + (container) => toIDeltaManagerFull(container.deltaManager).inbound, + ); } /** @@ -599,7 +605,10 @@ export class LoaderContainerTracker implements IOpProcessingController { * Pausing will switch the container to write mode. See `pauseProcessing` */ public async processOutgoing(...containers: IContainer[]) { - return this.processQueue(containers, (container) => container.deltaManager.outbound); + return this.processQueue( + containers, + (container) => toIDeltaManagerFull(container.deltaManager).outbound, + ); } /** @@ -678,12 +687,13 @@ export class LoaderContainerTracker implements IOpProcessingController { } }; - container.deltaManager.outbound.on("op", outHandler); - container.deltaManager.inbound.on("push", inHandler); + const deltaManagerFull = toIDeltaManagerFull(container.deltaManager); + deltaManagerFull.outbound.on("op", outHandler); + deltaManagerFull.inbound.on("push", inHandler); return () => { - container.deltaManager.outbound.off("op", outHandler); - container.deltaManager.inbound.off("push", inHandler); + deltaManagerFull.outbound.off("op", outHandler); + deltaManagerFull.inbound.off("push", inHandler); }; } @@ -726,7 +736,8 @@ export class LoaderContainerTracker implements IOpProcessingController { } }; debugOp(`${index}: ADD: clientId: ${container.clientId}`); - container.deltaManager.outbound.on("op", (messages) => { + const deltaManagerFull = toIDeltaManagerFull(container.deltaManager); + deltaManagerFull.outbound.on("op", (messages) => { for (const msg of messages) { debugOp( `${index}: OUT: ` + @@ -749,8 +760,8 @@ export class LoaderContainerTracker implements IOpProcessingController { ); }; }; - container.deltaManager.inbound.on("push", getInboundHandler("IN ")); - container.deltaManager.inbound.on("op", getInboundHandler("OP ")); + deltaManagerFull.inbound.on("push", getInboundHandler("IN ")); + deltaManagerFull.inbound.on("op", getInboundHandler("OP ")); container.deltaManager.on("connect", (details) => { debugOp(`${index}: CON: clientId: ${details.clientId}`); }); diff --git a/packages/test/test-utils/src/test/types/validateTestUtilsPrevious.generated.ts b/packages/test/test-utils/src/test/types/validateTestUtilsPrevious.generated.ts index 23bb8b2365d0..d14180f98964 100644 --- a/packages/test/test-utils/src/test/types/validateTestUtilsPrevious.generated.ts +++ b/packages/test/test-utils/src/test/types/validateTestUtilsPrevious.generated.ts @@ -85,6 +85,7 @@ declare type old_as_current_for_Interface_IProvideTestFluidObject = requireAssig * typeValidation.broken: * "Interface_IProvideTestFluidObject": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_IProvideTestFluidObject = requireAssignableTo, TypeOnly> /* @@ -103,4 +104,5 @@ declare type old_as_current_for_Interface_ITestFluidObject = requireAssignableTo * typeValidation.broken: * "Interface_ITestFluidObject": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_ITestFluidObject = requireAssignableTo, TypeOnly> diff --git a/packages/tools/devtools/devtools-core/package.json b/packages/tools/devtools/devtools-core/package.json index 507193ac0045..dc8fb4a2852a 100644 --- a/packages/tools/devtools/devtools-core/package.json +++ b/packages/tools/devtools/devtools-core/package.json @@ -168,7 +168,14 @@ } }, "typeValidation": { - "broken": {}, + "broken": { + "Interface_ContainerDevtoolsProps": { + "backCompat": false + }, + "Interface_FluidDevtoolsProps": { + "backCompat": false + } + }, "entrypoint": "alpha" } } diff --git a/packages/tools/devtools/devtools-core/src/test/types/validateDevtoolsCorePrevious.generated.ts b/packages/tools/devtools/devtools-core/src/test/types/validateDevtoolsCorePrevious.generated.ts index aaf3c5289081..3539a56d4ac0 100644 --- a/packages/tools/devtools/devtools-core/src/test/types/validateDevtoolsCorePrevious.generated.ts +++ b/packages/tools/devtools/devtools-core/src/test/types/validateDevtoolsCorePrevious.generated.ts @@ -49,6 +49,7 @@ declare type old_as_current_for_Interface_ContainerDevtoolsProps = requireAssign * typeValidation.broken: * "Interface_ContainerDevtoolsProps": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_ContainerDevtoolsProps = requireAssignableTo, TypeOnly> /* @@ -67,6 +68,7 @@ declare type old_as_current_for_Interface_FluidDevtoolsProps = requireAssignable * typeValidation.broken: * "Interface_FluidDevtoolsProps": {"backCompat": false} */ +// @ts-expect-error compatibility expected to be broken declare type current_as_old_for_Interface_FluidDevtoolsProps = requireAssignableTo, TypeOnly> /*