From e79c834895f9bb55287418b2e8da8662c9106717 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Mon, 6 Oct 2025 10:38:22 -0700 Subject: [PATCH 1/5] Make internal loadContainerRuntime take in FluidDataStoreRegistry --- .../attributor/src/mixinAttributor.ts | 52 +++---- .../container-runtime/src/containerRuntime.ts | 45 ++----- .../src/test/batching.spec.ts | 3 +- .../test/containerRuntime.extensions.spec.ts | 5 +- .../src/test/containerRuntime.spec.ts | 127 ++++++++++-------- .../src/test/hardwareStats.spec.ts | 3 +- .../test/runtimeLayerCompatValidation.spec.ts | 3 +- .../src/testContainerRuntimeFactory.ts | 8 +- .../replay-tool/src/replayFluidFactories.ts | 3 +- 9 files changed, 127 insertions(+), 122 deletions(-) diff --git a/packages/framework/attributor/src/mixinAttributor.ts b/packages/framework/attributor/src/mixinAttributor.ts index f9f64f7d7bae..ddff6ff24ce1 100644 --- a/packages/framework/attributor/src/mixinAttributor.ts +++ b/packages/framework/attributor/src/mixinAttributor.ts @@ -3,15 +3,13 @@ * Licensed under the MIT License. */ -import type { IContainerContext } from "@fluidframework/container-definitions/internal"; import { ContainerRuntime } from "@fluidframework/container-runtime/internal"; -import type { IContainerRuntimeOptions } from "@fluidframework/container-runtime/internal"; -import type { IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal"; import type { FluidObject } from "@fluidframework/core-interfaces"; import { assert } from "@fluidframework/core-utils/internal"; import type { + FluidDataStoreRegistryEntry, IContainerRuntimeBase, - NamedFluidDataStoreRegistryEntries, + IFluidDataStoreRegistry, } from "@fluidframework/runtime-definitions/internal"; import { loggerToMonitoringContext } from "@fluidframework/telemetry-utils/internal"; @@ -51,18 +49,12 @@ export const mixinAttributor = ( Base: typeof ContainerRuntime = ContainerRuntime, ): typeof ContainerRuntime => class ContainerRuntimeWithAttributor extends Base { - public static async loadRuntime(params: { - context: IContainerContext; - registryEntries: NamedFluidDataStoreRegistryEntries; - existing: boolean; - runtimeOptions?: IContainerRuntimeOptions; - containerScope?: FluidObject; - containerRuntimeCtor?: typeof ContainerRuntime; - provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise; - }): Promise { + public static override async loadRuntime( + params: Parameters[0], + ): Promise { const { context, - registryEntries, + registry, existing, provideEntryPoint, runtimeOptions, @@ -72,10 +64,26 @@ export const mixinAttributor = ( const mc = loggerToMonitoringContext(context.taggedLogger); const factory = new RuntimeAttributorFactory(); - const registryEntriesCopy: NamedFluidDataStoreRegistryEntries = [ - ...registryEntries, - [RuntimeAttributorFactory.type, Promise.resolve(factory)], - ]; + const registryCopy: IFluidDataStoreRegistry = { + async get(name: string): Promise { + if (name === RuntimeAttributorFactory.type) { + return factory; + } + return registry.get(name); + }, + get IFluidDataStoreRegistry(): IFluidDataStoreRegistry { + return this; + }, + }; + + if (registry.getSync !== undefined) { + registryCopy.getSync = (name: string) => { + if (name === RuntimeAttributorFactory.type) { + return factory; + } + return registry.getSync?.(name); + }; + } const shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false; if (shouldTrackAttribution) { const { options } = context; @@ -83,17 +91,15 @@ export const mixinAttributor = ( (options.attribution ??= {}).track = true; } - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - const runtime = (await Base.loadRuntime({ + const runtime = await Base.loadRuntime({ context, - registryEntries: registryEntriesCopy, + registry: registryCopy, provideEntryPoint, runtimeOptions, containerScope, existing, containerRuntimeCtor, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any)) as ContainerRuntimeWithAttributor; + }); let runtimeAttributor: IRuntimeAttributor | undefined; if (shouldTrackAttribution) { diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index 375a3666a20d..d5e7d402f5e3 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -786,7 +786,10 @@ export interface LoadContainerRuntimeParams { export async function loadContainerRuntime( params: LoadContainerRuntimeParams, ): Promise { - return ContainerRuntime.loadRuntime(params); + return ContainerRuntime.loadRuntime({ + ...params, + registry: new FluidDataStoreRegistry(params.registryEntries), + }); } const defaultMaxConsecutiveReconnects = 7; @@ -836,37 +839,19 @@ export class ContainerRuntime { /** * Load the stores from a snapshot and returns the runtime. - * @param params - An object housing the runtime properties: - * - context - Context of the container. - * - registryEntries - Mapping from data store types to their corresponding factories. - * - existing - Pass 'true' if loading from an existing snapshot. - * - requestHandler - (optional) Request handler for the request() method of the container runtime. - * Only relevant for back-compat while we remove the request() method and move fully to entryPoint as the main pattern. - * - runtimeOptions - Additional options to be passed to the runtime - * - containerScope - runtime services provided with context - * - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance. - * This allows mixin classes to leverage this method to define their own async initializer. - * - provideEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container. - * - minVersionForCollab - Minimum version of the FF runtime that this runtime supports collaboration with. - * This object should provide all the functionality that the Container is expected to provide to the loader layer. + * @param params - An object housing the runtime properties. + * {@link LoadContainerRuntimeParams} except with `registry` a instead of `registryEntries` and more `runtimeOptions`. */ - public static async loadRuntime(params: { - context: IContainerContext; - registryEntries: NamedFluidDataStoreRegistryEntries; - existing: boolean; - runtimeOptions?: IContainerRuntimeOptionsInternal; - containerScope?: FluidObject; - containerRuntimeCtor?: typeof ContainerRuntime; - /** - * @deprecated Will be removed once Loader LTS version is "2.0.0-internal.7.0.0". Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md - */ - requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise; - provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise; - minVersionForCollab?: MinimumVersionForCollab; - }): Promise { + public static async loadRuntime( + params: Omit & { + registry: IFluidDataStoreRegistry; + containerRuntimeCtor?: typeof ContainerRuntime; + runtimeOptions?: IContainerRuntimeOptionsInternal; + }, + ): Promise { const { context, - registryEntries, + registry, existing, requestHandler, provideEntryPoint, @@ -966,8 +951,6 @@ export class ContainerRuntime ? runtimeOptions.enableRuntimeIdCompressor : defaultConfigs.enableRuntimeIdCompressor; - const registry = new FluidDataStoreRegistry(registryEntries); - const tryFetchBlob = async (blobName: string): Promise => { const blobId = context.baseSnapshot?.blobs[blobName]; if (context.baseSnapshot !== undefined && blobId !== undefined) { diff --git a/packages/runtime/container-runtime/src/test/batching.spec.ts b/packages/runtime/container-runtime/src/test/batching.spec.ts index 83db07c254b3..51a3b649efb6 100644 --- a/packages/runtime/container-runtime/src/test/batching.spec.ts +++ b/packages/runtime/container-runtime/src/test/batching.spec.ts @@ -30,6 +30,7 @@ import { type SinonFakeTimers, createSandbox, useFakeTimers } from "sinon"; import type { ChannelCollection } from "../channelCollection.js"; import { ContainerRuntime } from "../containerRuntime.js"; +import { FluidDataStoreRegistry } from "../dataStoreRegistry.js"; import { ContainerMessageType } from "../messageTypes.js"; describe("Runtime batching", () => { @@ -81,7 +82,7 @@ describe("Runtime batching", () => { mockDeltaManager = new MockDeltaManager(); containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext(mockDeltaManager) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, diff --git a/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts b/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts index f3db7e77e537..83eb2d45df43 100644 --- a/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts +++ b/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts @@ -24,6 +24,7 @@ import { } from "@fluidframework/test-runtime-utils/internal"; import { ContainerRuntime } from "../containerRuntime.js"; +import { FluidDataStoreRegistry } from "../dataStoreRegistry.js"; const testExtensionId: ContainerExtensionId = "test:extension"; @@ -117,7 +118,7 @@ async function createRuntimeWithMockContext(isReadonly: boolean = false): Promis const context = new MockContext(isReadonly); const runtime = await ContainerRuntime.loadRuntime({ context, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: async () => ({}), }); @@ -133,7 +134,7 @@ async function createRuntimeWithoutConnectionState(isReadonly: boolean = false): delete context.getConnectionState; const runtime = await ContainerRuntime.loadRuntime({ context, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: async () => ({}), }); diff --git a/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts b/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts index 6656de091aed..473a3de12967 100644 --- a/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts +++ b/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts @@ -89,6 +89,7 @@ import { type IContainerRuntimeOptionsInternal, type UnknownIncomingTypedMessage, } from "../containerRuntime.js"; +import { FluidDataStoreRegistry } from "../dataStoreRegistry.js"; import { ContainerMessageType, type InboundSequencedContainerRuntimeMessage, @@ -325,7 +326,7 @@ describe("Runtime", () => { const logger = new MockLogger(); const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -353,7 +354,7 @@ describe("Runtime", () => { it("Default flush mode", async () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -368,7 +369,7 @@ describe("Runtime", () => { }; const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -387,7 +388,7 @@ describe("Runtime", () => { "Fluid.Container.enableOfflineLoad": true, }, }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -434,7 +435,7 @@ describe("Runtime", () => { "Fluid.Container.enableOfflineLoad": enableOfflineLoad, // batchId only stamped if true }, }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -519,7 +520,7 @@ describe("Runtime", () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -581,7 +582,7 @@ describe("Runtime", () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: mockContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on" }, provideEntryPoint: mockProvideEntryPoint, @@ -692,7 +693,7 @@ describe("Runtime", () => { containerRuntime = (await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -906,7 +907,7 @@ describe("Runtime", () => { }; containerRuntime = (await ContainerRuntime.loadRuntime({ context: getMockContextForOrderSequentially() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -1041,7 +1042,7 @@ describe("Runtime", () => { const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: undefined, containerScope: {}, @@ -1056,7 +1057,7 @@ describe("Runtime", () => { const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions: {}, @@ -1071,7 +1072,7 @@ describe("Runtime", () => { const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions: {}, @@ -1086,7 +1087,7 @@ describe("Runtime", () => { const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions: {}, @@ -1163,7 +1164,7 @@ describe("Runtime", () => { containerErrors.length = 0; containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContextForPendingStateProgressTracking() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions: { @@ -1431,7 +1432,7 @@ describe("Runtime", () => { }; containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions, @@ -1535,7 +1536,7 @@ describe("Runtime", () => { provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise; existing: boolean; runtimeOptions: IContainerRuntimeOptions; - registryEntries: NamedFluidDataStoreRegistryEntries; + registry: IFluidDataStoreRegistry; containerScope: FluidObject; }): Promise { // Note: we're mutating the parameter object here, normally a no-no, but shouldn't be @@ -1563,7 +1564,7 @@ describe("Runtime", () => { context: getMockContext() as IContainerContext, provideEntryPoint: async (containerRuntime) => myEntryPoint, existing: false, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), }); assert.equal( @@ -1578,7 +1579,7 @@ describe("Runtime", () => { it("Ensure private member is stable to support legacy usage", async () => { const containerRuntime_withSummarizeInternal = (await ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: mockProvideEntryPoint, })) as unknown as { @@ -1610,7 +1611,7 @@ describe("Runtime", () => { context: getMockContext() as IContainerContext, provideEntryPoint: async (ctrRuntime) => myEntryPoint, existing: false, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), }); // The entryPoint should come from the provided initialization function. @@ -1638,7 +1639,7 @@ describe("Runtime", () => { requestHandler: async (req, ctrRuntime) => myResponse, provideEntryPoint: async (ctrRuntime) => myEntryPoint, existing: false, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), }); // Calling request on the runtime should use the request handler we passed in the runtime's constructor. @@ -1670,7 +1671,7 @@ describe("Runtime", () => { beforeEach(async () => { containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -1760,7 +1761,7 @@ describe("Runtime", () => { it("Container load stats", async () => { await ContainerRuntime.loadRuntime({ context: localGetMockContext({}) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -1784,7 +1785,7 @@ describe("Runtime", () => { }; await ContainerRuntime.loadRuntime({ context: localGetMockContext(featureGates) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -1847,7 +1848,7 @@ describe("Runtime", () => { it("Loader not supported for async FlushMode, fallback to TurnBased", async () => { const runtime = await ContainerRuntime.loadRuntime({ context: localGetMockContext(features) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -1868,7 +1869,7 @@ describe("Runtime", () => { context: localGetMockContext( new Map([["referenceSequenceNumbers", true]]), ) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -1891,7 +1892,7 @@ describe("Runtime", () => { }; const runtime = await ContainerRuntime.loadRuntime({ context: localGetMockContext(undefined, compatDetails) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -1922,7 +1923,7 @@ describe("Runtime", () => { const settings = {}; containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext(settings) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: mockProvideEntryPoint, }); @@ -2181,7 +2182,7 @@ describe("Runtime", () => { }); const containerRuntime = await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: mockProvideEntryPoint, }); @@ -2210,7 +2211,7 @@ describe("Runtime", () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2248,7 +2249,7 @@ describe("Runtime", () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2298,7 +2299,7 @@ describe("Runtime", () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2319,7 +2320,7 @@ describe("Runtime", () => { const containerRuntime = await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2374,7 +2375,7 @@ describe("Runtime", () => { context: getMockContext({ settings: { "Fluid.Container.enableOfflineLoad": enableOfflineLoad }, }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2422,7 +2423,7 @@ describe("Runtime", () => { context: getMockContext({ settings: settings_enableOfflineLoad, }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2460,7 +2461,7 @@ describe("Runtime", () => { }, mockStorage, }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2678,7 +2679,9 @@ describe("Runtime", () => { createSnapshot(true /* addMissingDatastore */, false /* Don't set groupId property */); containerRuntime = await ContainerRuntime.loadRuntime({ context: containerContext, - registryEntries: [["@fluid-example/smde", Promise.resolve(entryDefault)]], + registry: new FluidDataStoreRegistry([ + ["@fluid-example/smde", Promise.resolve(entryDefault)], + ]), existing: true, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2706,7 +2709,9 @@ describe("Runtime", () => { containerContext.clientDetails.type = "summarizer"; containerRuntime = await ContainerRuntime.loadRuntime({ context: containerContext, - registryEntries: [["@fluid-example/smde", Promise.resolve(entryDefault)]], + registry: new FluidDataStoreRegistry([ + ["@fluid-example/smde", Promise.resolve(entryDefault)], + ]), existing: true, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2754,7 +2759,9 @@ describe("Runtime", () => { createSnapshot(true /* addMissingDatastore */); containerRuntime = await ContainerRuntime.loadRuntime({ context: containerContext, - registryEntries: [["@fluid-example/smde", Promise.resolve(entryDefault)]], + registry: new FluidDataStoreRegistry([ + ["@fluid-example/smde", Promise.resolve(entryDefault)], + ]), existing: true, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2816,7 +2823,9 @@ describe("Runtime", () => { createSnapshot(true /* addMissingDatastore */); containerRuntime = await ContainerRuntime.loadRuntime({ context: containerContext, - registryEntries: [["@fluid-example/smde", Promise.resolve(entryDefault)]], + registry: new FluidDataStoreRegistry([ + ["@fluid-example/smde", Promise.resolve(entryDefault)], + ]), existing: true, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2859,7 +2868,9 @@ describe("Runtime", () => { createSnapshot(true /* addMissingDatastore */); containerRuntime = await ContainerRuntime.loadRuntime({ context: containerContext, - registryEntries: [["@fluid-example/smde", Promise.resolve(entryDefault)]], + registry: new FluidDataStoreRegistry([ + ["@fluid-example/smde", Promise.resolve(entryDefault)], + ]), existing: true, runtimeOptions: { enableRuntimeIdCompressor: "on", @@ -2956,7 +2967,7 @@ describe("Runtime", () => { }; containerRuntime = (await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions, @@ -3527,7 +3538,7 @@ describe("Runtime", () => { { logger: remoteLogger }, "remoteMockClientId", ) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, requestHandler: undefined, runtimeOptions, @@ -3722,7 +3733,7 @@ describe("Runtime", () => { async () => ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { enableGroupedBatching: false, @@ -3748,7 +3759,7 @@ describe("Runtime", () => { async () => ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { createBlobPayloadPending: true, @@ -3773,7 +3784,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -3815,7 +3826,7 @@ describe("Runtime", () => { await assert.rejects(async () => { await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -3831,7 +3842,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -3869,7 +3880,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -3907,7 +3918,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -3945,7 +3956,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: mockProvideEntryPoint, minVersionForCollab, @@ -3981,7 +3992,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: { summaryOptions: { initialSummarizerDelayMs: 1 }, @@ -4049,7 +4060,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -4088,7 +4099,7 @@ describe("Runtime", () => { const logger = new MockLogger(); await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -4142,7 +4153,7 @@ describe("Runtime", () => { await assert.rejects(async () => { await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions, provideEntryPoint: mockProvideEntryPoint, @@ -4156,7 +4167,7 @@ describe("Runtime", () => { await assert.doesNotReject(async () => { await ContainerRuntime.loadRuntime({ context: getMockContext({ logger }) as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, // We would normally throw (since `createBlobPayloadPending` requires 2.40), but since we did // not explicity set minVersionForCollab, we allow it. @@ -4173,7 +4184,7 @@ describe("Runtime", () => { beforeEach("init", async () => { containerRuntime = (await ContainerRuntime.loadRuntime({ context: getMockContext() as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -4239,7 +4250,7 @@ describe("Runtime", () => { }) as IContainerContext; containerRuntime = (await ContainerRuntime.loadRuntime({ context: mockContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, @@ -4257,7 +4268,7 @@ describe("Runtime", () => { }) as IContainerContext; containerRuntime = (await ContainerRuntime.loadRuntime({ context: mockContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, runtimeOptions: {}, provideEntryPoint: mockProvideEntryPoint, diff --git a/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts b/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts index 4bcdd44580c0..1f2f60f50e36 100644 --- a/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts +++ b/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts @@ -15,6 +15,7 @@ import { } from "@fluidframework/test-runtime-utils/internal"; import { ContainerRuntime, getDeviceSpec } from "../containerRuntime.js"; +import { FluidDataStoreRegistry } from "../dataStoreRegistry.js"; function setNavigator( // eslint-disable-next-line @rushstack/no-new-null -- testing behavior with global @@ -41,7 +42,7 @@ describe("Hardware Stats", () => { const loadContainer = async () => ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), runtimeOptions: { summaryOptions: { summaryConfigOverrides: { state: "disabled" }, diff --git a/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts b/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts index 403726ec6b0b..e7aeb2c9a685 100644 --- a/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts +++ b/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts @@ -30,6 +30,7 @@ import { import Sinon from "sinon"; import { ContainerRuntime } from "../containerRuntime.js"; +import { FluidDataStoreRegistry } from "../dataStoreRegistry.js"; import { pkgVersion } from "../packageVersion.js"; import { runtimeCompatDetailsForLoader, @@ -141,7 +142,7 @@ async function createAndLoadRuntime( await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registryEntries: [], + registry: new FluidDataStoreRegistry([]), existing: false, provideEntryPoint: async () => ({ myProp: "myValue", diff --git a/packages/test/test-utils/src/testContainerRuntimeFactory.ts b/packages/test/test-utils/src/testContainerRuntimeFactory.ts index 86535a0aeefa..a5bd57b6a6d7 100644 --- a/packages/test/test-utils/src/testContainerRuntimeFactory.ts +++ b/packages/test/test-utils/src/testContainerRuntimeFactory.ts @@ -7,8 +7,8 @@ import { IContainerContext, IRuntime } from "@fluidframework/container-definitio import { ContainerRuntime, DefaultSummaryConfiguration, + FluidDataStoreRegistry, type IContainerRuntimeOptionsInternal, - type LoadContainerRuntimeParams, type MinimumVersionForCollab, } from "@fluidframework/container-runtime/internal"; import { @@ -166,10 +166,10 @@ export const createTestContainerRuntimeFactory = ( }; return containerRuntimeCtor.loadRuntime({ context, - registryEntries: [ + registry: new FluidDataStoreRegistry([ ["default", Promise.resolve(this.dataStoreFactory)], [this.type, Promise.resolve(this.dataStoreFactory)], - ], + ]), // eslint-disable-next-line import/no-deprecated requestHandler: buildRuntimeRequestHandler(getDefaultObject, ...this.requestHandlers), provideEntryPoint, @@ -177,7 +177,7 @@ export const createTestContainerRuntimeFactory = ( containerScope: context.scope, existing, minVersionForCollab: this.minVersionForCollab, - } satisfies LoadContainerRuntimeParams); + }); } }; }; diff --git a/packages/tools/replay-tool/src/replayFluidFactories.ts b/packages/tools/replay-tool/src/replayFluidFactories.ts index cf052a52a055..e73a413763d7 100644 --- a/packages/tools/replay-tool/src/replayFluidFactories.ts +++ b/packages/tools/replay-tool/src/replayFluidFactories.ts @@ -13,6 +13,7 @@ import { SharedCell } from "@fluidframework/cell/internal"; import type { IContainerContext } from "@fluidframework/container-definitions/internal"; import { ContainerRuntime, + FluidDataStoreRegistry, type IContainerRuntimeOptions, } from "@fluidframework/container-runtime/internal"; import type { IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal"; @@ -68,7 +69,7 @@ export class ReplayRuntimeFactory extends RuntimeFactoryHelper { }, existing, runtimeOptions: this.runtimeOptions, - registryEntries: this.registries, + registry: new FluidDataStoreRegistry(this.registries), }); } } From 4658473644174e2511111c62e6e9a8cf5f2be29a Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Mon, 6 Oct 2025 11:08:49 -0700 Subject: [PATCH 2/5] Update packages/runtime/container-runtime/src/containerRuntime.ts Co-authored-by: Joshua Smithrud <54606601+Josmithr@users.noreply.github.com> --- packages/runtime/container-runtime/src/containerRuntime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index d5e7d402f5e3..8ce2e5d5ed8c 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -840,7 +840,7 @@ export class ContainerRuntime /** * Load the stores from a snapshot and returns the runtime. * @param params - An object housing the runtime properties. - * {@link LoadContainerRuntimeParams} except with `registry` a instead of `registryEntries` and more `runtimeOptions`. + * {@link LoadContainerRuntimeParams} except with `registry` instead of `registryEntries` and more `runtimeOptions`. */ public static async loadRuntime( params: Omit & { From 6732268ec9e4e8b92728cdee15ce4bc64b125f2e Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Mon, 6 Oct 2025 11:31:27 -0700 Subject: [PATCH 3/5] Better comments --- .../container-runtime/src/containerRuntime.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index 8ce2e5d5ed8c..6c441bfcba62 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -737,7 +737,9 @@ export interface LoadContainerRuntimeParams { */ existing: boolean; /** - * Additional options to be passed to the runtime + * Additional options to be passed to the runtime. + * @remarks + * Defaults to `{}`. */ runtimeOptions?: IContainerRuntimeOptions; /** @@ -844,8 +846,19 @@ export class ContainerRuntime */ public static async loadRuntime( params: Omit & { + /** + * Mapping from data store types to their corresponding factories. + */ registry: IFluidDataStoreRegistry; + /** + * Constructor to use to create the ContainerRuntime instance. + * @remarks + * Defaults to {@link ContainerRuntime}. + */ containerRuntimeCtor?: typeof ContainerRuntime; + /** + * {@link LoadContainerRuntimeParams.runtimeOptions}, except with additional internal only options. + */ runtimeOptions?: IContainerRuntimeOptionsInternal; }, ): Promise { From 2602c805d979c31fbd09c8ce7de005a5d4104ae2 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Mon, 6 Oct 2025 12:02:22 -0700 Subject: [PATCH 4/5] reintroduce loadRuntime2 --- .../attributor/src/mixinAttributor.ts | 31 +---- .../container-runtime/src/containerRuntime.ts | 36 ++++- .../src/test/batching.spec.ts | 2 +- .../test/containerRuntime.extensions.spec.ts | 4 +- .../src/test/containerRuntime.spec.ts | 124 +++++++++--------- .../src/test/hardwareStats.spec.ts | 2 +- .../test/runtimeLayerCompatValidation.spec.ts | 3 +- .../src/testContainerRuntimeFactory.ts | 5 +- .../replay-tool/src/replayFluidFactories.ts | 3 +- 9 files changed, 108 insertions(+), 102 deletions(-) diff --git a/packages/framework/attributor/src/mixinAttributor.ts b/packages/framework/attributor/src/mixinAttributor.ts index ddff6ff24ce1..128f89ff96bd 100644 --- a/packages/framework/attributor/src/mixinAttributor.ts +++ b/packages/framework/attributor/src/mixinAttributor.ts @@ -7,9 +7,8 @@ import { ContainerRuntime } from "@fluidframework/container-runtime/internal"; import type { FluidObject } from "@fluidframework/core-interfaces"; import { assert } from "@fluidframework/core-utils/internal"; import type { - FluidDataStoreRegistryEntry, IContainerRuntimeBase, - IFluidDataStoreRegistry, + NamedFluidDataStoreRegistryEntries, } from "@fluidframework/runtime-definitions/internal"; import { loggerToMonitoringContext } from "@fluidframework/telemetry-utils/internal"; @@ -54,7 +53,7 @@ export const mixinAttributor = ( ): Promise { const { context, - registry, + registryEntries, existing, provideEntryPoint, runtimeOptions, @@ -64,26 +63,10 @@ export const mixinAttributor = ( const mc = loggerToMonitoringContext(context.taggedLogger); const factory = new RuntimeAttributorFactory(); - const registryCopy: IFluidDataStoreRegistry = { - async get(name: string): Promise { - if (name === RuntimeAttributorFactory.type) { - return factory; - } - return registry.get(name); - }, - get IFluidDataStoreRegistry(): IFluidDataStoreRegistry { - return this; - }, - }; - - if (registry.getSync !== undefined) { - registryCopy.getSync = (name: string) => { - if (name === RuntimeAttributorFactory.type) { - return factory; - } - return registry.getSync?.(name); - }; - } + const registryEntriesCopy: NamedFluidDataStoreRegistryEntries = [ + ...registryEntries, + [RuntimeAttributorFactory.type, Promise.resolve(factory)], + ]; const shouldTrackAttribution = mc.config.getBoolean(enableOnNewFileKey) ?? false; if (shouldTrackAttribution) { const { options } = context; @@ -93,7 +76,7 @@ export const mixinAttributor = ( const runtime = await Base.loadRuntime({ context, - registry: registryCopy, + registryEntries: registryEntriesCopy, provideEntryPoint, runtimeOptions, containerScope, diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index 6c441bfcba62..0f21c81b1bb2 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -788,10 +788,7 @@ export interface LoadContainerRuntimeParams { export async function loadContainerRuntime( params: LoadContainerRuntimeParams, ): Promise { - return ContainerRuntime.loadRuntime({ - ...params, - registry: new FluidDataStoreRegistry(params.registryEntries), - }); + return ContainerRuntime.loadRuntime(params); } const defaultMaxConsecutiveReconnects = 7; @@ -842,9 +839,38 @@ export class ContainerRuntime /** * Load the stores from a snapshot and returns the runtime. * @param params - An object housing the runtime properties. - * {@link LoadContainerRuntimeParams} except with `registry` instead of `registryEntries` and more `runtimeOptions`. + * {@link LoadContainerRuntimeParams} except internal, while still having layer compat obligations. + * @privateRemarks + * Despite this being `@internal`, this has layer compat implications so changing it is problematic. + * Instead of changing this, {@link loadRuntime2} was added. + * This is directly invoked by `createTestContainerRuntimeFactory`: + * if that is the only cross version use, + * then `createTestContainerRuntimeFactory` could be updated to handle both versions or use the stable {@link loadContainerRuntime} API, + * and `loadRuntime` could be removed (replaced by `loadRuntime2` which could be renamed back to `loadRuntime`). */ public static async loadRuntime( + params: LoadContainerRuntimeParams & { + /** + * Constructor to use to create the ContainerRuntime instance. + * @remarks + * Defaults to {@link ContainerRuntime}. + */ + containerRuntimeCtor?: typeof ContainerRuntime; + }, + ): Promise { + return ContainerRuntime.loadRuntime2({ + ...params, + registry: new FluidDataStoreRegistry(params.registryEntries), + }); + } + + /** + * Load the stores from a snapshot and returns the runtime. + * @remarks + * Same as {@link ContainerRuntime.loadRuntime}, + * but with `registry` instead of `registryEntries` and more `runtimeOptions`. + */ + public static async loadRuntime2( params: Omit & { /** * Mapping from data store types to their corresponding factories. diff --git a/packages/runtime/container-runtime/src/test/batching.spec.ts b/packages/runtime/container-runtime/src/test/batching.spec.ts index 51a3b649efb6..2c4143b1b5e9 100644 --- a/packages/runtime/container-runtime/src/test/batching.spec.ts +++ b/packages/runtime/container-runtime/src/test/batching.spec.ts @@ -80,7 +80,7 @@ describe("Runtime batching", () => { beforeEach(async () => { mockDeltaManager = new MockDeltaManager(); - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext(mockDeltaManager) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, diff --git a/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts b/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts index 83eb2d45df43..1552df8f3969 100644 --- a/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts +++ b/packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts @@ -116,7 +116,7 @@ async function createRuntimeWithMockContext(isReadonly: boolean = false): Promis context: MockContext; }> { const context = new MockContext(isReadonly); - const runtime = await ContainerRuntime.loadRuntime({ + const runtime = await ContainerRuntime.loadRuntime2({ context, registry: new FluidDataStoreRegistry([]), existing: false, @@ -132,7 +132,7 @@ async function createRuntimeWithoutConnectionState(isReadonly: boolean = false): const context = new MockContext(isReadonly); // Delete the getConnectionState method before creating the runtime delete context.getConnectionState; - const runtime = await ContainerRuntime.loadRuntime({ + const runtime = await ContainerRuntime.loadRuntime2({ context, registry: new FluidDataStoreRegistry([]), existing: false, diff --git a/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts b/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts index 473a3de12967..897a2b4f52db 100644 --- a/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts +++ b/packages/runtime/container-runtime/src/test/containerRuntime.spec.ts @@ -324,7 +324,7 @@ describe("Runtime", () => { describe("IdCompressor", () => { it("finalizes idRange on attach", async () => { const logger = new MockLogger(); - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -352,7 +352,7 @@ describe("Runtime", () => { describe("Batching", () => { it("Default flush mode", async () => { - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -367,7 +367,7 @@ describe("Runtime", () => { const runtimeOptions: IContainerRuntimeOptionsInternal = { flushMode: FlushMode.Immediate, }; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -382,7 +382,7 @@ describe("Runtime", () => { let batchBegin = 0; let batchEnd = 0; let callsToEnsure = 0; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ settings: { "Fluid.Container.enableOfflineLoad": true, @@ -429,7 +429,7 @@ describe("Runtime", () => { for (const enableOfflineLoad of [true, undefined]) it("Replaying ops should resend in correct order, with batch ID if applicable", async () => { - const containerRuntime = (await ContainerRuntime.loadRuntime({ + const containerRuntime = (await ContainerRuntime.loadRuntime2({ context: getMockContext({ settings: { "Fluid.Container.enableOfflineLoad": enableOfflineLoad, // batchId only stamped if true @@ -518,7 +518,7 @@ describe("Runtime", () => { return 999; // CSN not used in test asserts below }; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -580,7 +580,7 @@ describe("Runtime", () => { const mockContext = getMockContext({ connected }) as IContainerContext; const mockDeltaManager = mockContext.deltaManager as MockDeltaManager; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: mockContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -691,7 +691,7 @@ describe("Runtime", () => { flushMode, }; - containerRuntime = (await ContainerRuntime.loadRuntime({ + containerRuntime = (await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -905,7 +905,7 @@ describe("Runtime", () => { }, flushMode, }; - containerRuntime = (await ContainerRuntime.loadRuntime({ + containerRuntime = (await ContainerRuntime.loadRuntime2({ context: getMockContextForOrderSequentially() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1040,7 +1040,7 @@ describe("Runtime", () => { it("should NOT be set to dirty if context is attached with no pending ops", async () => { const mockContext = createMockContext(AttachState.Attached, false); const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1055,7 +1055,7 @@ describe("Runtime", () => { it("should be set to dirty if context is attached with pending ops", async () => { const mockContext = createMockContext(AttachState.Attached, true); const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1070,7 +1070,7 @@ describe("Runtime", () => { it("should be set to dirty if context is attaching", async () => { const mockContext = createMockContext(AttachState.Attaching, false); const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1085,7 +1085,7 @@ describe("Runtime", () => { it("should be set to dirty if context is detached", async () => { const mockContext = createMockContext(AttachState.Detached, false); const updateDirtyStateStub = sandbox.stub(mockContext, "updateDirtyContainerState"); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1162,7 +1162,7 @@ describe("Runtime", () => { beforeEach(async () => { containerErrors.length = 0; - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContextForPendingStateProgressTracking() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1430,7 +1430,7 @@ describe("Runtime", () => { const runtimeOptions: IContainerRuntimeOptionsInternal = { enableGroupedBatching: false, }; - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1523,14 +1523,14 @@ describe("Runtime", () => { }); }); describe("Supports mixin classes", () => { - it("new loadRuntime method works", async () => { + it("new loadRuntime2 method works", async () => { const makeMixin = ( Base: typeof ContainerRuntime, methodName: string, methodReturn: T, ) => class MixinContainerRuntime extends Base { - public static async loadRuntime(params: { + public static async loadRuntime2(params: { context: IContainerContext; containerRuntimeCtor?: typeof ContainerRuntime; provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise; @@ -1544,7 +1544,7 @@ describe("Runtime", () => { params.containerRuntimeCtor = params.containerRuntimeCtor ?? MixinContainerRuntime; params.containerScope = params.containerScope ?? params.context.scope; - return Base.loadRuntime(params); + return Base.loadRuntime2(params); } public [methodName](): T { @@ -1560,7 +1560,7 @@ describe("Runtime", () => { makeMixin(ContainerRuntime, "method1", "mixed in return"), "method2", 42, - ).loadRuntime({ + ).loadRuntime2({ context: getMockContext() as IContainerContext, provideEntryPoint: async (containerRuntime) => myEntryPoint, existing: false, @@ -1577,7 +1577,7 @@ describe("Runtime", () => { // A legacy partner team overrides the summarizeInternal method to add custom data to the Summary. // Let's make sure we don't break them inadvertently, while we work to move them to a better pattern. it("Ensure private member is stable to support legacy usage", async () => { - const containerRuntime_withSummarizeInternal = (await ContainerRuntime.loadRuntime({ + const containerRuntime_withSummarizeInternal = (await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1603,11 +1603,11 @@ describe("Runtime", () => { }); describe("EntryPoint initialized correctly", () => { - it("when using new loadRuntime method", async () => { + it("when using new loadRuntime2 method", async () => { const myEntryPoint: FluidObject = { myProp: "myValue", }; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, provideEntryPoint: async (ctrRuntime) => myEntryPoint, existing: false, @@ -1624,7 +1624,7 @@ describe("Runtime", () => { ); }); - it("loadRuntime accepts both requestHandlers and entryPoint", async () => { + it("loadRuntime2 accepts both requestHandlers and entryPoint", async () => { const myResponse: IResponse = { mimeType: "fluid/object", value: "hello!", @@ -1634,7 +1634,7 @@ describe("Runtime", () => { myProp: "myValue", }; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, requestHandler: async (req, ctrRuntime) => myResponse, provideEntryPoint: async (ctrRuntime) => myEntryPoint, @@ -1669,7 +1669,7 @@ describe("Runtime", () => { let pendingStateManager: PendingStateManager; beforeEach(async () => { - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1759,7 +1759,7 @@ describe("Runtime", () => { const mergedRuntimeOptions = { ...defaultRuntimeOptions, ...runtimeOptions } as const; it("Container load stats", async () => { - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: localGetMockContext({}) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1783,7 +1783,7 @@ describe("Runtime", () => { "Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs": 1337, "Fluid.ContainerRuntime.DisableFlushBeforeProcess": true, }; - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: localGetMockContext(featureGates) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1846,7 +1846,7 @@ describe("Runtime", () => { ]), ]) { it("Loader not supported for async FlushMode, fallback to TurnBased", async () => { - const runtime = await ContainerRuntime.loadRuntime({ + const runtime = await ContainerRuntime.loadRuntime2({ context: localGetMockContext(features) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1865,7 +1865,7 @@ describe("Runtime", () => { } it("Loader supported for async FlushMode", async () => { - const runtime = await ContainerRuntime.loadRuntime({ + const runtime = await ContainerRuntime.loadRuntime2({ context: localGetMockContext( new Map([["referenceSequenceNumbers", true]]), ) as IContainerContext, @@ -1890,7 +1890,7 @@ describe("Runtime", () => { generation: 1, supportedFeatures: new Set(), }; - const runtime = await ContainerRuntime.loadRuntime({ + const runtime = await ContainerRuntime.loadRuntime2({ context: localGetMockContext(undefined, compatDetails) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -1921,7 +1921,7 @@ describe("Runtime", () => { beforeEach(async () => { const settings = {}; - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext(settings) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -2180,7 +2180,7 @@ describe("Runtime", () => { mockStorage: new MockStorageService(), loadedFromVersion: latestVersion, }); - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -2209,7 +2209,7 @@ describe("Runtime", () => { it("No Props. No pending state", async () => { const logger = new MockLogger(); - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -2247,7 +2247,7 @@ describe("Runtime", () => { it("No Props. Some pending state", async () => { const logger = new MockLogger(); - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -2297,7 +2297,7 @@ describe("Runtime", () => { it("sessionExpiryTimerStarted. No pending state", async () => { const logger = new MockLogger(); - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -2318,7 +2318,7 @@ describe("Runtime", () => { it("sessionExpiryTimerStarted. Some pending state", async () => { const logger = new MockLogger(); - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -2371,7 +2371,7 @@ describe("Runtime", () => { describe("Duplicate Batch Detection", () => { for (const enableOfflineLoad of [undefined, true]) { it(`DuplicateBatchDetector enablement matches Offline load (${enableOfflineLoad === true ? "ENABLED" : "DISABLED"})`, async () => { - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ settings: { "Fluid.Container.enableOfflineLoad": enableOfflineLoad }, }) as IContainerContext, @@ -2419,7 +2419,7 @@ describe("Runtime", () => { it("Can roundrip DuplicateBatchDetector state through summary/snapshot", async () => { // Duplicate Batch Detection requires OfflineLoad enabled const settings_enableOfflineLoad = { "Fluid.Container.enableOfflineLoad": true }; - const containerRuntime = await ContainerRuntime.loadRuntime({ + const containerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext({ settings: settings_enableOfflineLoad, }) as IContainerContext, @@ -2452,7 +2452,7 @@ describe("Runtime", () => { // Hardcode readblob fn to return the blob contents put in the summary readBlob: async (_id) => stringToBuffer(blob.content as string, "utf8"), }; - const containerRuntime2 = await ContainerRuntime.loadRuntime({ + const containerRuntime2 = await ContainerRuntime.loadRuntime2({ context: getMockContext({ settings: settings_enableOfflineLoad, baseSnapshot: { @@ -2677,7 +2677,7 @@ describe("Runtime", () => { // but the "missingDataStore" is aliased, it fails if the snapshot for it does not have loadingGroupId to fetch // the omitted snapshot contents. createSnapshot(true /* addMissingDatastore */, false /* Don't set groupId property */); - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: containerContext, registry: new FluidDataStoreRegistry([ ["@fluid-example/smde", Promise.resolve(entryDefault)], @@ -2707,7 +2707,7 @@ describe("Runtime", () => { }; createSnapshot(true /* addMissingDatastore */); containerContext.clientDetails.type = "summarizer"; - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: containerContext, registry: new FluidDataStoreRegistry([ ["@fluid-example/smde", Promise.resolve(entryDefault)], @@ -2757,7 +2757,7 @@ describe("Runtime", () => { return snapshotWithContents; }; createSnapshot(true /* addMissingDatastore */); - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: containerContext, registry: new FluidDataStoreRegistry([ ["@fluid-example/smde", Promise.resolve(entryDefault)], @@ -2821,7 +2821,7 @@ describe("Runtime", () => { return snapshotWithContents; }; createSnapshot(true /* addMissingDatastore */); - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: containerContext, registry: new FluidDataStoreRegistry([ ["@fluid-example/smde", Promise.resolve(entryDefault)], @@ -2866,7 +2866,7 @@ describe("Runtime", () => { return snapshotWithContents; }; createSnapshot(true /* addMissingDatastore */); - containerRuntime = await ContainerRuntime.loadRuntime({ + containerRuntime = await ContainerRuntime.loadRuntime2({ context: containerContext, registry: new FluidDataStoreRegistry([ ["@fluid-example/smde", Promise.resolve(entryDefault)], @@ -2965,7 +2965,7 @@ describe("Runtime", () => { const runtimeOptions: IContainerRuntimeOptionsInternal = { enableGroupedBatching: false, }; - containerRuntime = (await ContainerRuntime.loadRuntime({ + containerRuntime = (await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3533,7 +3533,7 @@ describe("Runtime", () => { const runtimeOptions: IContainerRuntimeOptionsInternal = { enableGroupedBatching: false, }; - remoteContainerRuntime = await ContainerRuntime.loadRuntime({ + remoteContainerRuntime = await ContainerRuntime.loadRuntime2({ context: getMockContext( { logger: remoteLogger }, "remoteMockClientId", @@ -3731,7 +3731,7 @@ describe("Runtime", () => { it("Throws when op compression is on and op grouping is off", async () => { await assert.rejects( async () => - ContainerRuntime.loadRuntime({ + ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3757,7 +3757,7 @@ describe("Runtime", () => { it("Throws when createBlobPayloadPending is on and explicitSchemaControl is not enabled", async () => { await assert.rejects( async () => - ContainerRuntime.loadRuntime({ + ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3782,7 +3782,7 @@ describe("Runtime", () => { describe("Default Configurations", () => { it("minVersionForCollab not provided", async () => { const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3824,7 +3824,7 @@ describe("Runtime", () => { it(`throws when minVersionForCollab = ${version}`, async () => { const logger = new MockLogger(); await assert.rejects(async () => { - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3840,7 +3840,7 @@ describe("Runtime", () => { it("minVersionForCollab = 1.0.0", async () => { const minVersionForCollab = "1.0.0"; const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3878,7 +3878,7 @@ describe("Runtime", () => { it('minVersionForCollab = 2.0.0-defaults ("default")', async () => { const minVersionForCollab = "2.0.0-defaults"; const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3916,7 +3916,7 @@ describe("Runtime", () => { it("minVersionForCollab = 2.0.0 (explicit)", async () => { const minVersionForCollab = "2.0.0"; const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3954,7 +3954,7 @@ describe("Runtime", () => { it("minVersionForCollab = 2.20.0", async () => { const minVersionForCollab = "2.20.0"; const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -3990,7 +3990,7 @@ describe("Runtime", () => { it("minVersionForCollab not provided, with manual configs", async () => { const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4058,7 +4058,7 @@ describe("Runtime", () => { ]) it(desc, async () => { const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4097,7 +4097,7 @@ describe("Runtime", () => { it("minVersionForCollab = pkgVersion", async () => { const minVersionForCollab = pkgVersion; const logger = new MockLogger(); - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4151,7 +4151,7 @@ describe("Runtime", () => { const logger = new MockLogger(); const minVersionForCollab = "1.0.0"; await assert.rejects(async () => { - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4165,7 +4165,7 @@ describe("Runtime", () => { it("does not throw if minVersionForCollab is not set and the default is incompatible with runtimeOptions", async () => { const logger = new MockLogger(); await assert.doesNotReject(async () => { - await ContainerRuntime.loadRuntime({ + await ContainerRuntime.loadRuntime2({ context: getMockContext({ logger }) as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4182,7 +4182,7 @@ describe("Runtime", () => { let containerRuntime: ContainerRuntime_WithPrivates; beforeEach("init", async () => { - containerRuntime = (await ContainerRuntime.loadRuntime({ + containerRuntime = (await ContainerRuntime.loadRuntime2({ context: getMockContext() as IContainerContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4248,7 +4248,7 @@ describe("Runtime", () => { const mockContext = getMockContext({ attachState: AttachState.Attaching, }) as IContainerContext; - containerRuntime = (await ContainerRuntime.loadRuntime({ + containerRuntime = (await ContainerRuntime.loadRuntime2({ context: mockContext, registry: new FluidDataStoreRegistry([]), existing: false, @@ -4266,7 +4266,7 @@ describe("Runtime", () => { const mockContext = getMockContext({ attachState: AttachState.Detached, }) as IContainerContext; - containerRuntime = (await ContainerRuntime.loadRuntime({ + containerRuntime = (await ContainerRuntime.loadRuntime2({ context: mockContext, registry: new FluidDataStoreRegistry([]), existing: false, diff --git a/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts b/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts index 1f2f60f50e36..547a30d897d5 100644 --- a/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts +++ b/packages/runtime/container-runtime/src/test/hardwareStats.spec.ts @@ -40,7 +40,7 @@ describe("Hardware Stats", () => { mockLogger.events.filter((event) => event.eventName === "DeviceSpec"); const loadContainer = async () => - ContainerRuntime.loadRuntime({ + ContainerRuntime.loadRuntime2({ context: mockContext as IContainerContext, registry: new FluidDataStoreRegistry([]), runtimeOptions: { diff --git a/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts b/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts index e7aeb2c9a685..403726ec6b0b 100644 --- a/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts +++ b/packages/runtime/container-runtime/src/test/runtimeLayerCompatValidation.spec.ts @@ -30,7 +30,6 @@ import { import Sinon from "sinon"; import { ContainerRuntime } from "../containerRuntime.js"; -import { FluidDataStoreRegistry } from "../dataStoreRegistry.js"; import { pkgVersion } from "../packageVersion.js"; import { runtimeCompatDetailsForLoader, @@ -142,7 +141,7 @@ async function createAndLoadRuntime( await ContainerRuntime.loadRuntime({ context: mockContext as IContainerContext, - registry: new FluidDataStoreRegistry([]), + registryEntries: [], existing: false, provideEntryPoint: async () => ({ myProp: "myValue", diff --git a/packages/test/test-utils/src/testContainerRuntimeFactory.ts b/packages/test/test-utils/src/testContainerRuntimeFactory.ts index a5bd57b6a6d7..74da56fcd364 100644 --- a/packages/test/test-utils/src/testContainerRuntimeFactory.ts +++ b/packages/test/test-utils/src/testContainerRuntimeFactory.ts @@ -7,7 +7,6 @@ import { IContainerContext, IRuntime } from "@fluidframework/container-definitio import { ContainerRuntime, DefaultSummaryConfiguration, - FluidDataStoreRegistry, type IContainerRuntimeOptionsInternal, type MinimumVersionForCollab, } from "@fluidframework/container-runtime/internal"; @@ -166,10 +165,10 @@ export const createTestContainerRuntimeFactory = ( }; return containerRuntimeCtor.loadRuntime({ context, - registry: new FluidDataStoreRegistry([ + registryEntries: [ ["default", Promise.resolve(this.dataStoreFactory)], [this.type, Promise.resolve(this.dataStoreFactory)], - ]), + ], // eslint-disable-next-line import/no-deprecated requestHandler: buildRuntimeRequestHandler(getDefaultObject, ...this.requestHandlers), provideEntryPoint, diff --git a/packages/tools/replay-tool/src/replayFluidFactories.ts b/packages/tools/replay-tool/src/replayFluidFactories.ts index e73a413763d7..cf052a52a055 100644 --- a/packages/tools/replay-tool/src/replayFluidFactories.ts +++ b/packages/tools/replay-tool/src/replayFluidFactories.ts @@ -13,7 +13,6 @@ import { SharedCell } from "@fluidframework/cell/internal"; import type { IContainerContext } from "@fluidframework/container-definitions/internal"; import { ContainerRuntime, - FluidDataStoreRegistry, type IContainerRuntimeOptions, } from "@fluidframework/container-runtime/internal"; import type { IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal"; @@ -69,7 +68,7 @@ export class ReplayRuntimeFactory extends RuntimeFactoryHelper { }, existing, runtimeOptions: this.runtimeOptions, - registry: new FluidDataStoreRegistry(this.registries), + registryEntries: this.registries, }); } } From 7b617ca81cf727cb63c3901b5c931a5a335a01b2 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Tue, 14 Oct 2025 16:24:54 -0700 Subject: [PATCH 5/5] Update comments --- .../container-runtime/src/containerRuntime.ts | 13 +++++++------ .../test-utils/src/testContainerRuntimeFactory.ts | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index d226cd4ffe66..6025d65633c3 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -841,12 +841,13 @@ export class ContainerRuntime * @param params - An object housing the runtime properties. * {@link LoadContainerRuntimeParams} except internal, while still having layer compat obligations. * @privateRemarks - * Despite this being `@internal`, this has layer compat implications so changing it is problematic. - * Instead of changing this, {@link loadRuntime2} was added. - * This is directly invoked by `createTestContainerRuntimeFactory`: - * if that is the only cross version use, - * then `createTestContainerRuntimeFactory` could be updated to handle both versions or use the stable {@link loadContainerRuntime} API, - * and `loadRuntime` could be removed (replaced by `loadRuntime2` which could be renamed back to `loadRuntime`). + * Despite this being `@internal`, `@fluidframework/test-utils` uses it in `createTestContainerRuntimeFactory` and assumes multiple versions of the package expose the same API. + * + * Also note that `mixinAttributor` from `@fluid-experimental/attributor` overrides this function: + * that will have to be updated if changing the signature of this function as well. + * + * Assuming these usages are updated appropriately, + * `loadRuntime` could be removed (replaced by `loadRuntime2` which could be renamed back to `loadRuntime`). */ public static async loadRuntime( params: LoadContainerRuntimeParams & { diff --git a/packages/test/test-utils/src/testContainerRuntimeFactory.ts b/packages/test/test-utils/src/testContainerRuntimeFactory.ts index 74da56fcd364..e0c8b0b8d855 100644 --- a/packages/test/test-utils/src/testContainerRuntimeFactory.ts +++ b/packages/test/test-utils/src/testContainerRuntimeFactory.ts @@ -163,6 +163,10 @@ export const createTestContainerRuntimeFactory = ( } return undefined; // continue search }; + + // This usage of `containerRuntimeCtor.loadRuntime`, an `@internal` API, called on past versions of this package, + // adds an extra constraint that makes changing that API more difficult than it otherwise would be. + // Actual customers / apps should not be dependent on stability of this API, but this code is, at least for now. return containerRuntimeCtor.loadRuntime({ context, registryEntries: [