/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import { FlushMode, type MinimumVersionForCollab, } from "@fluidframework/runtime-definitions/internal"; import { configValueToMinVersionForCollab, getConfigsForMinVersionForCollab, validateConfigMapOverrides, type ConfigMap, type ConfigValidationMap, } from "@fluidframework/runtime-utils/internal"; import { disabledCompressionConfig, enabledCompressionConfig, } from "./compressionDefinitions.js"; import type { ContainerRuntimeOptionsInternal } from "./containerRuntime.js"; /** * Subset of the {@link ContainerRuntimeOptionsInternal} properties which * affect {@link IDocumentSchemaFeatures}. * * @remarks * When a new option is added to {@link ContainerRuntimeOptionsInternal}, we * must consider if it changes the DocumentSchema. If so, then a corresponding * entry must be added to {@link runtimeOptionsAffectingDocSchemaConfigMap} * below. If not, then it must be omitted from this type. * * Note: `Omit` is used instead of `Pick` to ensure that all new options are * included in this type by default. If any new properties are added to * {@link ContainerRuntimeOptionsInternal}, they will be included in this * type unless explicitly omitted. This will prevent us from forgetting to * account for any new properties in the future. */ export type RuntimeOptionsAffectingDocSchema = Omit< ContainerRuntimeOptionsInternal, | "chunkSizeInBytes" | "maxBatchSizeInBytes" | "loadSequenceNumberVerification" | "summaryOptions" | "stagingModeAutoFlushThreshold" | "disableSchemaUpgrade" >; /** * Subset of {@link RuntimeOptionsAffectingDocSchema} which existed prior to the introduction of explicitSchemaControl. * * @remarks * Runtime options that affect document schema should generally require explicitSchemaControl to be enabled. * However, to prevent disruption to existing customers, options that existed prior to explicitSchemaControl * do not explicity require explicitSchemaControl to be enabled. Do not add new options to this list. */ type RuntimeOptionKeysPredatingExplicitSchemaControl = keyof Pick< RuntimeOptionsAffectingDocSchema, | "explicitSchemaControl" | "compressionOptions" | "enableRuntimeIdCompressor" | "flushMode" | "gcOptions" | "enableGroupedBatching" >; /** * List of keys of {@link RuntimeOptionsAffectingDocSchema} which existed prior to the introduction of explicitSchemaControl. * * @remarks * Runtime options that affect document schema should generally require explicitSchemaControl to be enabled. * However, to prevent disruption to existing customers, options that existed prior to explicitSchemaControl * do not explicity require explicitSchemaControl to be enabled. Do not add new keys to this list. */ const keysOfOptionsPredatingExplicitSchemaControl = new Set([ "explicitSchemaControl", "compressionOptions", "enableRuntimeIdCompressor", "flushMode", "gcOptions", "enableGroupedBatching", ]) satisfies Set; /** * Subset of {@link RuntimeOptionsAffectingDocSchema} which require explicitSchemaControl to be enabled. */ export type RuntimeOptionKeysThatRequireExplicitSchemaControl = keyof Omit< RuntimeOptionsAffectingDocSchema, RuntimeOptionKeysPredatingExplicitSchemaControl >; /** * Mapping of RuntimeOptionsAffectingDocSchema to their compatibility related configs. * * Each key in this map corresponds to a property in RuntimeOptionsAffectingDocSchema. The value is an object that maps MinimumVersionForCollab * to the appropriate default value for that property to supporting that MinimumVersionForCollab. If clients running MinimumVersionForCollab X are able to understand * the format changes introduced by the property, then the default value for that MinimumVersionForCollab will enable the feature associated with the property. * Otherwise, the feature will be disabled. * * For example if the minVersionForCollab is a 1.x version (i.e. "1.5.0"), then the default value for `enableGroupedBatching` will be false since 1.x * clients do not understand the document format when batching is enabled. If the minVersionForCollab is a 2.x client (i.e. "2.0.0" or later), then the * default value for `enableGroupedBatching` will be true because clients running 2.0 or later will be able to understand the format changes associated * with the batching feature. */ const runtimeOptionsAffectingDocSchemaConfigMap: ConfigMap = { enableGroupedBatching: { "1.0.0": false, "2.0.0-defaults": true, }, compressionOptions: { "1.0.0": disabledCompressionConfig, "2.0.0-defaults": enabledCompressionConfig, }, enableRuntimeIdCompressor: { // For IdCompressorMode, `undefined` represents a logical state (off). // However, to satisfy the Required<> constraint while // `exactOptionalPropertyTypes` is `false` (TODO: AB#8215), we need // to have it defined, so we trick the type checker here. "1.0.0": undefined, // We do not yet want to enable idCompressor by default since it will // increase bundle sizes, and not all customers will benefit from it. // Therefore, we will require customers to explicitly enable it. We // are keeping it as a DocSchema affecting option for now as this may // change in the future. }, explicitSchemaControl: { "1.0.0": false, // This option's intention is to prevent 1.x clients from joining sessions // when enabled. This is set to true when the minVersionForCollab is set // to >=2.0.0 (explicitly). This is different than other 2.0 defaults // because it was not enabled by default prior to the implementation of // `minVersionForCollab`. // `defaultMinVersionForCollab` is set to "2.0.0-defaults" which "2.0.0" // does not satisfy to avoiding enabling this option by default as of // `minVersionForCollab` introduction, which could be unexpected. // Only enable as a default when `minVersionForCollab` is specified at // 2.0.0+. "2.0.0": true, }, flushMode: { // Note: 1.x clients are compatible with TurnBased flushing, but here we elect to remain on Immediate flush mode // as a work-around for inability to send batches larger than 1Mb. Immediate flushing keeps batches smaller as // fewer messages will be included per flush. "1.0.0": FlushMode.Immediate, "2.0.0-defaults": FlushMode.TurnBased, }, gcOptions: { "1.0.0": {}, // Although sweep is supported in 2.x, it is disabled by default until minVersionForCollab>=3.0.0 to be extra safe. // Note that enabling this is a significant change, that should likely be announced in the relevant version: // It would be bad if this simple caused the enablement when when the current package version passed this point without anyone being aware. // This is configuration targeting a future versions, which is not supported. // TODO: when preparing 3.0 (or at some later point), consider enabling this by default for clients 3.0 or newer // (and add user facing documentation indicating this is enabled by that version). // "3.0.0": { enableGCSweep: true }, }, createBlobPayloadPending: { // This feature is new and disabled by default. In the future we will enable it by default, but we have not // closed on the version where that will happen yet. Probably a .10 release since blob functionality is not // exposed on the `@public` API surface. "1.0.0": undefined, }, }; /** * Keys of {@link ContainerRuntimeOptionsInternal} that require explicitSchemaControl to be enabled. */ export const runtimeOptionKeysThatRequireExplicitSchemaControl = ( Object.keys( runtimeOptionsAffectingDocSchemaConfigMap, ) as (keyof RuntimeOptionsAffectingDocSchema)[] ).filter((key) => { return !keysOfOptionsPredatingExplicitSchemaControl.has( key as RuntimeOptionKeysPredatingExplicitSchemaControl, ); }) as RuntimeOptionKeysThatRequireExplicitSchemaControl[]; // A lot of the information in this seems redundant with whats defined above. Might be nice to combine them somehow. const runtimeOptionsAffectingDocSchemaConfigValidationMap: ConfigValidationMap = { enableGroupedBatching: configValueToMinVersionForCollab([ [false, "1.0.0"], [true, "2.0.0-defaults"], ]), compressionOptions: configValueToMinVersionForCollab([ [{ ...disabledCompressionConfig }, "1.0.0"], [{ ...enabledCompressionConfig }, "2.0.0-defaults"], ]), enableRuntimeIdCompressor: configValueToMinVersionForCollab([ [undefined, "1.0.0"], ["on", "2.0.0-defaults"], ["delayed", "2.0.0-defaults"], ]), explicitSchemaControl: configValueToMinVersionForCollab([ [false, "1.0.0"], [true, "2.0.0-defaults"], ]), flushMode: configValueToMinVersionForCollab([ [FlushMode.Immediate, "1.0.0"], [FlushMode.TurnBased, "2.0.0-defaults"], ]), gcOptions: configValueToMinVersionForCollab([ [{ enableGCSweep: undefined }, "1.0.0"], [{ enableGCSweep: true }, "2.0.0-defaults"], ]), createBlobPayloadPending: configValueToMinVersionForCollab([ [undefined, "1.0.0"], [true, "2.40.0"], ]), }; /** * Returns the default RuntimeOptionsAffectingDocSchema configuration for a given minVersionForCollab. */ export function getMinVersionForCollabDefaults( minVersionForCollab: MinimumVersionForCollab, ): RuntimeOptionsAffectingDocSchema { return getConfigsForMinVersionForCollab( minVersionForCollab, runtimeOptionsAffectingDocSchemaConfigMap, ); } /** * Validates if the runtime options passed in from the user are compatible with the minVersionForCollab. * For example, if a user sets the `enableGroupedBatching` option to true, but the minVersionForCollab * is set to "1.0.0", then we should throw a UsageError since 1.x clients do not support batching. * */ export function validateRuntimeOptions( minVersionForCollab: MinimumVersionForCollab, runtimeOptions: Partial, ): void { validateConfigMapOverrides( minVersionForCollab, runtimeOptions, runtimeOptionsAffectingDocSchemaConfigValidationMap, ); }