Skip to content

Commit

Permalink
Move closeAndGetPendingLocalState to IContainerExperimental (#16302)
Browse files Browse the repository at this point in the history
This change deprecates the experimental method
closeAndGetPendingLocalState on IContainer and moves it to
IContainerExperimental.
IContainerExperimental is an interface that is easily casted to, which
enables partners to access experimental features for testing and
evaluation.
Moving the experimental method off IContainer will reduce exposure and
churn on that production interface as we iterate on and finalize our
experimental features.
Experimental features should not be used in production environments.

---------

Co-authored-by: Tony Murphy <[email protected]>
  • Loading branch information
anthony-murphy and anthony-murphy authored Jul 10, 2023
1 parent b57cd6a commit 93151af
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 21 deletions.
13 changes: 13 additions & 0 deletions .changeset/lazy-coats-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@fluidframework/container-definitions": minor
"@fluidframework/container-loader": minor
"@fluid-experimental/tree": minor
"@fluid-experimental/tree2": minor
---

Move closeAndGetPendingLocalState to IContainerExperimental

This change deprecates the experimental method closeAndGetPendingLocalState on IContainer and moves it to IContainerExperimental.
IContainerExperimental is an interface that is easily casted to, which enables partners to access experimental features for testing and evaluation.
Moving the experimental method off IContainer will reduce exposure and churn on that production interface as we iterate on and finalize our experimental features.
Experimental features should not be used in production environments.
4 changes: 4 additions & 0 deletions UPCOMING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
## IDeltaManager members disposed and dispose() deprecated

Directly calling dispose() on the IDeltaManager puts the system in an inconsistent state, and inspecting the disposed state of the IDeltaManager is not recommended (instead, prefer to inspect either the IContainer.disposed, IContainerRuntime.disposed, or IFluidDataStoreRuntime.disposed depending on your scenario). These members have been deprecated from the interface and will be removed in an upcoming release.

## Move closeAndGetPendingLocalState to IContainerExperimental

This change deprecates the experimental method closeAndGetPendingLocalState on IContainer and moves it to IContainerExperimental. IContainerExperimental is an interface that is easily casted to, which enables partners to access experimental features for testing and evaluation. Moving the experimental method off IContainer will reduce exposure and churn on that production interface as we iterate on and finalize our experimental features. Experimental features should not be used in production environments.
1 change: 1 addition & 0 deletions api-report/container-definitions.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export interface IContainer extends IEventProvider<IContainerEvents>, IFluidRout
readonly audience: IAudience;
readonly clientId?: string | undefined;
close(error?: ICriticalContainerError): void;
// @deprecated (undocumented)
closeAndGetPendingLocalState(): string;
readonly closed: boolean;
connect(): void;
Expand Down
5 changes: 3 additions & 2 deletions api-report/container-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComp
load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;
}

// @internal
// @public
export interface IContainerExperimental extends IContainer {
getPendingLocalState(): string;
closeAndGetPendingLocalState(): string;
getPendingLocalState?(): string;
}

// @public
Expand Down
4 changes: 2 additions & 2 deletions experimental/dds/tree/src/test/utilities/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { v5 as uuidv5 } from 'uuid';
import { expect } from 'chai';
import { LocalServerTestDriver } from '@fluid-internal/test-drivers';
import { SummaryCollection, DefaultSummaryConfiguration } from '@fluidframework/container-runtime';
import { Loader, waitContainerToCatchUp } from '@fluidframework/container-loader';
import { IContainerExperimental, Loader, waitContainerToCatchUp } from '@fluidframework/container-loader';
import { requestFluidObject } from '@fluidframework/runtime-utils';
import {
MockContainerRuntimeFactory,
Expand Down Expand Up @@ -677,7 +677,7 @@ export async function waitForSummary(mainContainer: IContainer): Promise<string>
*/
export async function withContainerOffline<TReturn>(
provider: ITestObjectProvider,
container: IContainer,
container: IContainerExperimental,
action: () => TReturn
): Promise<{ actionReturn: TReturn; pendingLocalState: string }> {
await provider.ensureSynchronized();
Expand Down
2 changes: 2 additions & 0 deletions packages/common/container-definitions/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ export interface IContainer extends IEventProvider<IContainerEvents>, IFluidRout
close(error?: ICriticalContainerError): void;

/**
* @deprecated - This is moved to the IContainerExperimental interface. To access you should cast IContainerExperimental before attempting to use
*
* Closes the container and returns serialized local state intended to be
* given to a newly loaded container.
* @experimental
Expand Down
6 changes: 5 additions & 1 deletion packages/loader/container-loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"typescript": "~4.5.5"
},
"typeValidation": {
"broken": {}
"broken": {
"InterfaceDeclaration_IContainerExperimental": {
"backCompat": false
}
}
}
}
12 changes: 10 additions & 2 deletions packages/loader/container-loader/src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2392,7 +2392,7 @@ export class Container

/**
* IContainer interface that includes experimental features still under development.
* @internal
* @experimental
*/
export interface IContainerExperimental extends IContainer {
/**
Expand All @@ -2403,5 +2403,13 @@ export interface IContainerExperimental extends IContainer {
* @experimental misuse of this API can result in duplicate op submission and potential document corruption
* {@link https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/closeAndGetPendingLocalState.md}
*/
getPendingLocalState(): string;
getPendingLocalState?(): string;

/**
* Closes the container and returns serialized local state intended to be
* given to a newly loaded container.
* @experimental
* {@link https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/closeAndGetPendingLocalState.md}
*/
closeAndGetPendingLocalState(): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ declare function get_current_InterfaceDeclaration_IContainerExperimental():
declare function use_old_InterfaceDeclaration_IContainerExperimental(
use: TypeOnly<old.IContainerExperimental>);
use_old_InterfaceDeclaration_IContainerExperimental(
// @ts-expect-error compatibility expected to be broken
get_current_InterfaceDeclaration_IContainerExperimental());

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Loader,
ILoaderProps,
waitContainerToCatchUp,
IContainerExperimental,
} from "@fluidframework/container-loader";
import {
DriverErrorType,
Expand Down Expand Up @@ -331,7 +332,9 @@ describeNoCompat("Container", (getTestObjectProvider) => {
runtimeFactory,
);

const container = await localTestObjectProvider.makeTestContainer(testContainerConfig);
const container: IContainerExperimental = await localTestObjectProvider.makeTestContainer(
testContainerConfig,
);

const pendingLocalState: IPendingLocalState = JSON.parse(
container.closeAndGetPendingLocalState(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "@fluidframework/test-utils";
import { describeNoCompat } from "@fluid-internal/test-version-utils";
import { ConfigTypes, IConfigProviderBase } from "@fluidframework/telemetry-utils";
import { IContainerExperimental } from "@fluidframework/container-loader";

const configProvider = (settings: Record<string, ConfigTypes>): IConfigProviderBase => ({
getRawConfig: (name: string): ConfigTypes => settings[name],
Expand All @@ -44,7 +45,7 @@ type MapCallback = (
map: SharedMap,
) => void | Promise<void>;

const getPendingStateWithoutClose = (container: IContainer): string => {
const getPendingStateWithoutClose = (container: IContainerExperimental): string => {
const containerClose = container.close;
container.close = (message) => assert(message === undefined);
const pendingState = container.closeAndGetPendingLocalState();
Expand Down
23 changes: 13 additions & 10 deletions packages/test/test-end-to-end-tests/src/test/stashedOps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const testKey2 = "another test key";
const testValue = "test value";
const testIncrementValue = 5;

const getPendingStateWithoutClose = (container: IContainer): string => {
const getPendingStateWithoutClose = (container: IContainerExperimental): string => {
const containerClose = container.close;
container.close = (message) => assert(message === undefined);
const pendingState = container.closeAndGetPendingLocalState();
Expand All @@ -102,7 +102,7 @@ const getPendingOps = async (
send: boolean,
cb: SharedObjCallback = () => undefined,
) => {
const container = await args.loadTestContainer(testContainerConfig);
const container: IContainerExperimental = await args.loadTestContainer(testContainerConfig);
await waitForContainerConnection(container);
const dataStore = await requestFluidObject<ITestFluidObject>(container, "default");

Expand Down Expand Up @@ -146,7 +146,7 @@ async function loadOffline(
provider: ITestObjectProvider,
request: IRequest,
pendingLocalState?: string,
): Promise<{ container: IContainer; connect: () => void }> {
): Promise<{ container: IContainerExperimental; connect: () => void }> {
const p = new Deferred();
const documentServiceFactory = provider.driver.createDocumentServiceFactory();

Expand Down Expand Up @@ -189,7 +189,7 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {
let provider: ITestObjectProvider;
let url;
let loader: IHostLoader;
let container1: IContainer;
let container1: IContainerExperimental;
let map1: SharedMap;
let string1: SharedString;
let cell1: SharedCell;
Expand Down Expand Up @@ -1291,7 +1291,7 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {

it("works for detached container", async function () {
const loader2 = provider.makeTestLoader(testContainerConfig);
const detachedContainer = await loader2.createDetachedContainer(
const detachedContainer: IContainerExperimental = await loader2.createDetachedContainer(
provider.defaultCodeDetails,
);
const dataStore = await requestFluidObject<ITestFluidObject>(detachedContainer, "default");
Expand Down Expand Up @@ -1320,7 +1320,8 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {

const summary = detachedContainer.serialize();
detachedContainer.close();
const rehydratedContainer = await loader2.rehydrateDetachedContainerFromSnapshot(summary);
const rehydratedContainer: IContainerExperimental =
await loader2.rehydrateDetachedContainerFromSnapshot(summary);
const dataStore2 = await requestFluidObject<ITestFluidObject>(
rehydratedContainer,
"default",
Expand Down Expand Up @@ -1369,7 +1370,9 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {
// TODO: https://github.com/microsoft/FluidFramework/issues/10729
it("can stash between summary op and ack", async function () {
map1.set("test op 1", "test op 1");
const container = await provider.loadTestContainer(testContainerConfig);
const container: IContainerExperimental = await provider.loadTestContainer(
testContainerConfig,
);
const pendingOps = await new Promise<string>((resolve, reject) =>
container.on("op", (op) => {
if (op.type === "summarize") {
Expand All @@ -1394,7 +1397,7 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {
let pendingState;
// always delete stash blob on "connected" event
container.on("connected", (clientId: string) => {
pendingState = container.getPendingLocalState();
pendingState = container.getPendingLocalState?.();
// the pending data in the stash blob may not have changed, but the clientId should match our new
// clientId, which will now be used to attempt to resubmit pending changes
assert.strictEqual(clientId, JSON.parse(pendingState).clientId);
Expand Down Expand Up @@ -1436,7 +1439,7 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {
let pendingState;
// always delete stash blob on "connected" event
container.on("connected", (clientId: string) => {
pendingState = container.getPendingLocalState();
pendingState = container.getPendingLocalState?.();
// the pending data in the stash blob may not have changed, but the clientId should match our new
// clientId, which will now be used to attempt to resubmit pending changes
assert.strictEqual(clientId, JSON.parse(pendingState).clientId);
Expand Down Expand Up @@ -1469,7 +1472,7 @@ describeNoCompat("stashed ops", (getTestObjectProvider) => {
it("handles stashed ops with reference sequence number of 0", async function () {
const provider2 = getTestObjectProvider();
const loader2 = provider2.makeTestLoader(testContainerConfig);
const container = await createAndAttachContainer(
const container: IContainerExperimental = await createAndAttachContainer(
provider2.defaultCodeDetails,
loader2,
provider2.driver.createCreateNewRequest(createDocumentId()),
Expand Down
4 changes: 2 additions & 2 deletions packages/test/test-service-load/src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
TestDriverTypes,
DriverEndpoint,
} from "@fluidframework/test-driver-definitions";
import { Loader, ConnectionState } from "@fluidframework/container-loader";
import { Loader, ConnectionState, IContainerExperimental } from "@fluidframework/container-loader";
import { requestFluidObject } from "@fluidframework/runtime-utils";
import { IRequestHeader } from "@fluidframework/core-interfaces";
import { IContainer, LoaderHeader } from "@fluidframework/container-definitions";
Expand Down Expand Up @@ -446,7 +446,7 @@ function scheduleContainerClose(

async function scheduleOffline(
dsf: FaultInjectionDocumentServiceFactory,
container: IContainer,
container: IContainerExperimental,
runConfig: IRunConfig,
offlineDelayMinMs: number,
offlineDelayMaxMs: number,
Expand Down

0 comments on commit 93151af

Please sign in to comment.