Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(container-runtime): Add IProtocolOptions and CompatibilityMode to container-runtime #23951

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

```ts

// @public
export type CompatibilityMode = "1" | "2";
export { CompatibilityMode }

export { compatibilityModeRuntimeOptions }

// @public
export type ContainerAttachProps<T = unknown> = T;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

```ts

// @public
export type CompatibilityMode = "1" | "2";
export { CompatibilityMode }

export { compatibilityModeRuntimeOptions }

// @public
export type ContainerAttachProps<T = unknown> = T;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

```ts

// @public
export type CompatibilityMode = "1" | "2";
export { CompatibilityMode }

export { compatibilityModeRuntimeOptions }

// @public
export type ContainerAttachProps<T = unknown> = T;
Expand Down
6 changes: 5 additions & 1 deletion packages/framework/fluid-static/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export {
export { createDOProviderContainerRuntimeFactory } from "./rootDataObject.js";
export { createServiceAudience } from "./serviceAudience.js";
export type {
CompatibilityMode,
ContainerSchema,
ContainerAttachProps,
IConnection,
Expand All @@ -33,3 +32,8 @@ export type {
MemberChangedListener,
Myself,
} from "./types.js";

// Re-export so other packages don't need to pull in container-runtime
// TODO: Should we re-export?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a great reason to re-export the API in fluid-static, but I believe this would be a breaking change to a public API. Do we need to stage removing the API completely from fluid-static?

export type { CompatibilityMode } from "@fluidframework/container-runtime";
export { compatibilityModeRuntimeOptions } from "@fluidframework/container-runtime/internal";
4 changes: 2 additions & 2 deletions packages/framework/fluid-static/src/rootDataObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import {
DataObjectFactory,
} from "@fluidframework/aqueduct/internal";
import type { IRuntimeFactory } from "@fluidframework/container-definitions/internal";
import type { CompatibilityMode } from "@fluidframework/container-runtime";
import { compatibilityModeRuntimeOptions } from "@fluidframework/container-runtime/internal";
import type { IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal";
import type { FluidObject, IFluidLoadable } from "@fluidframework/core-interfaces";
import type { IDirectory } from "@fluidframework/map/internal";
import type { SharedObjectKind } from "@fluidframework/shared-object-base";
import type { ISharedObjectKind } from "@fluidframework/shared-object-base/internal";

import { compatibilityModeRuntimeOptions } from "./compatibilityConfiguration.js";
import type {
CompatibilityMode,
ContainerSchema,
IRootDataObject,
LoadableObjectKind,
Expand Down
6 changes: 0 additions & 6 deletions packages/framework/fluid-static/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import type { IEvent, IEventProvider, IFluidLoadable } from "@fluidframework/cor
import type { SharedObjectKind } from "@fluidframework/shared-object-base";
import type { ISharedObjectKind } from "@fluidframework/shared-object-base/internal";

/**
* Valid compatibility modes that may be specified when creating a DOProviderContainerRuntimeFactory.
* @public
*/
export type CompatibilityMode = "1" | "2";

/**
* A mapping of string identifiers to instantiated `DataObject`s or `SharedObject`s.
* @internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

```ts

// @public
export type CompatibilityMode = "1" | "2";

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
// @alpha
export const AllowTombstoneRequestHeaderKey = "allowTombstone";

// @public
export type CompatibilityMode = "1" | "2";

// @alpha
export enum CompressionAlgorithms {
// (undocumented)
Expand Down Expand Up @@ -192,6 +195,7 @@ export interface IContainerRuntimeMetadata extends ICreateContainerMetadata, IGC
// @alpha
export interface IContainerRuntimeOptions {
readonly chunkSizeInBytes?: number;
readonly compatibilityMode?: CompatibilityMode;
readonly compressionOptions?: ICompressionRuntimeOptions;
// @deprecated
readonly enableGroupedBatching?: boolean;
Expand All @@ -201,6 +205,7 @@ export interface IContainerRuntimeOptions {
readonly gcOptions?: IGCRuntimeOptions;
readonly loadSequenceNumberVerification?: "close" | "log" | "bypass";
readonly maxBatchSizeInBytes?: number;
readonly protocolOptions?: IProtocolOptions;
// (undocumented)
readonly summaryOptions?: ISummaryRuntimeOptions;
}
Expand Down Expand Up @@ -354,6 +359,16 @@ export interface IOnDemandSummarizeOptions extends ISummarizeOptions {
readonly retryOnFailure?: boolean;
}

// @alpha
export interface IProtocolOptions {
readonly compressionOptions?: ICompressionRuntimeOptions;
readonly enableGCSweep?: true | undefined;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcOptions is a tricky case, since it contains a compatability/protocol related option. Ultimately, I decided to just include that specific option (enableGCSweep) in IProtocolOptions and leave the rest of in IContainerRuntimeOptions.

// @deprecated
readonly enableGroupedBatching?: boolean;
readonly enableRuntimeIdCompressor?: IdCompressorMode;
readonly explicitSchemaControl?: boolean;
}

// @alpha @deprecated
export interface IRefreshSummaryAckOptions {
readonly ackHandle: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

```ts

// @public
export type CompatibilityMode = "1" | "2";

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

```ts

// @public
export type CompatibilityMode = "1" | "2";

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,32 @@
* Licensed under the MIT License.
*/

import { FlushMode } from "@fluidframework/runtime-definitions/internal";

import {
CompressionAlgorithms,
type IContainerRuntimeOptionsInternal,
} from "@fluidframework/container-runtime/internal";
import { FlushMode } from "@fluidframework/runtime-definitions/internal";
} from "./containerRuntime.js";

/**
* Valid compatibility modes that may be specified when creating a DOProviderContainerRuntimeFactory.
* @public
*/
export type CompatibilityMode = "1" | "2";

import type { CompatibilityMode } from "./types.js";
/**
* The default compatibility mode is "1".
* This is based on our current cross-client compat policy, which states we must support the most recent
* adjacent public major version (currently 1.x).
* This value will need to be updated if our compat policy changes, or we release a major public version.
* @public
*/
export const defaultCompatibilityMode: CompatibilityMode = "1";

/**
* The CompatibilityMode selected determines the set of runtime options to use. In "1" mode we support
* full interop with true 1.x clients, while in "2" mode we only support interop with 2.x clients.
* @internal
*/
export const compatibilityModeRuntimeOptions: Record<
CompatibilityMode,
Expand Down
87 changes: 85 additions & 2 deletions packages/runtime/container-runtime/src/containerRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ import {
getSummaryForDatastores,
wrapContext,
} from "./channelCollection.js";
import {
defaultCompatibilityMode,
type CompatibilityMode,
} from "./compatibilityConfiguration.js";
import { IPerfSignalReport, ReportOpPerfTelemetry } from "./connectionTelemetry.js";
import { ContainerFluidHandleContext } from "./containerHandleContext.js";
import { channelToDataStore } from "./dataStore.js";
Expand Down Expand Up @@ -486,12 +490,71 @@ export interface ICompressionRuntimeOptions {
readonly compressionAlgorithm: CompressionAlgorithms;
}

/**
* TODO: TSDoc update
* Options for container runtime related to protocol/data format.
* All clients connected to the same container must be able to understand the same protocol.
* @legacy
* @alpha
*/
export interface IProtocolOptions {
/**
* Enable the IdCompressor in the runtime.
* @experimental Not ready for use.
*/
readonly enableRuntimeIdCompressor?: IdCompressorMode;

/**
* If enabled, the runtime will group messages within a batch into a single
* message to be sent to the service.
* The grouping and ungrouping of such messages is handled by the "OpGroupingManager".
*
* By default, the feature is enabled. This feature can only be disabled when compression is also disabled.
* @deprecated The ability to disable Grouped Batching is deprecated and will be removed in a future release. This feature is required for the proper functioning of the Fluid Framework.
*/
readonly enableGroupedBatching?: boolean;

/**
* When this property is set to true, it requires runtime to control is document schema properly through ops
* The benefit of this mode is that clients who do not understand schema will fail in predictable way, with predictable message,
* and will not attempt to limp along, which could cause data corruptions and crashes in random places.
* When this property is not set (or set to false), runtime operates in legacy mode, where new features (modifying document schema)
* are engaged as they become available, without giving legacy clients any chance to fail predictably.
*/
readonly explicitSchemaControl?: boolean;

/**
* Flag that if true, will enable the full Sweep Phase of garbage collection for this session,
* where Tombstoned objects are permanently deleted from the container.
*
* IMPORTANT: This only applies if this document is allowed to run Sweep Phase.
*
* Current default behavior is for Sweep Phase not to delete Tombstoned objects,
* but merely to prevent them from being loaded.
*/
readonly enableGCSweep?: true | undefined;

/**
* Enables the runtime to compress ops. See {@link ICompressionRuntimeOptions}.
*/
readonly compressionOptions?: ICompressionRuntimeOptions;
}

/**
* Options for container runtime.
* @legacy
* @alpha
*/
export interface IContainerRuntimeOptions {
/**
* TODO: TSDoc
*/
readonly protocolOptions?: IProtocolOptions;
/**
* TODO: TSDoc
*/
readonly compatibilityMode?: CompatibilityMode;

readonly summaryOptions?: ISummaryRuntimeOptions;
readonly gcOptions?: IGCRuntimeOptions;
/**
Expand Down Expand Up @@ -990,21 +1053,39 @@ export class ContainerRuntime

const mc = loggerToMonitoringContext(logger);

// Options without overlap with IProtocolOptions
const {
summaryOptions = {},
gcOptions = {},
loadSequenceNumberVerification = "close",
flushMode = defaultFlushMode,
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
chunkSizeInBytes = defaultChunkSizeInBytes,
protocolOptions = {},
compatibilityMode = defaultCompatibilityMode,
}: IContainerRuntimeOptionsInternal = runtimeOptions;
// Options with overlap with IProtocolOptions
let {
compressionOptions = runtimeOptions.enableGroupedBatching === false
? disabledCompressionConfig // Compression must be disabled if Grouping is disabled
: defaultCompressionConfig,
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
enableRuntimeIdCompressor,
chunkSizeInBytes = defaultChunkSizeInBytes,
enableGroupedBatching = true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something I noticed - we have enableGroupedBatching (and compression) on by default. Based on recent compat policy discussions, I believe this should be disabled by default, since it breaks compataiblity with an adjacent major public release (1.x).

explicitSchemaControl = false,
}: IContainerRuntimeOptionsInternal = runtimeOptions;

// While we transition to using IProtocolOptions, we will need to handle duplicate properties.
// For now, any properties defined in protocolOptions will overwrite duplicate properties in runtimeOptions.
enableGroupedBatching = protocolOptions.enableGroupedBatching ?? enableGroupedBatching;
explicitSchemaControl = protocolOptions.explicitSchemaControl ?? explicitSchemaControl;
compressionOptions =
enableGroupedBatching === false
? disabledCompressionConfig // Compression must be disabled if Grouping is disabled
: defaultCompressionConfig;
gcOptions.enableGCSweep = protocolOptions.enableGCSweep ?? gcOptions.enableGCSweep;
enableRuntimeIdCompressor =
protocolOptions.enableRuntimeIdCompressor ?? enableRuntimeIdCompressor;

const registry = new FluidDataStoreRegistry(registryEntries);

const tryFetchBlob = async <T>(blobName: string): Promise<T | undefined> => {
Expand Down Expand Up @@ -1206,6 +1287,8 @@ export class ContainerRuntime
enableRuntimeIdCompressor: enableRuntimeIdCompressor as "on" | "delayed",
enableGroupedBatching,
explicitSchemaControl,
protocolOptions,
compatibilityMode,
};

const runtime = new containerRuntimeCtor(
Expand Down
5 changes: 5 additions & 0 deletions packages/runtime/container-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export {
CompressionAlgorithms,
RuntimeHeaderData,
disabledCompressionConfig,
IProtocolOptions,
} from "./containerRuntime.js";
export {
ContainerMessageType,
Expand Down Expand Up @@ -121,3 +122,7 @@ export {
IFluidDataStoreContextEvents,
} from "./dataStoreContext.js";
export { DataStoreContexts } from "./dataStoreContexts.js";
export {
CompatibilityMode,
compatibilityModeRuntimeOptions,
} from "./compatibilityConfiguration.js";
2 changes: 2 additions & 0 deletions packages/test/test-service-load/src/optionsMatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ export function generateRuntimeOptions(
enableRuntimeIdCompressor: ["on", undefined, "delayed"],
enableGroupedBatching: [true, false],
explicitSchemaControl: [true, false],
protocolOptions: [undefined, {}], // TODO: This will change in the future
compatibilityMode: ["1", "2"],
};

const pairwiseOptions = generatePairwiseOptions<IContainerRuntimeOptionsInternal>(
Expand Down
Loading