-
Notifications
You must be signed in to change notification settings - Fork 537
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
tree: Add alpha tree configuration APIs #22701
Changes from 1 commit
14162e9
fe8daec
f728197
fa6c729
b601566
53d1395
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
--- | ||
"fluid-framework": minor | ||
"@fluidframework/tree": minor | ||
--- | ||
--- | ||
"section": tree | ||
--- | ||
|
||
Add alpha API for providing SharedTree configuration options | ||
|
||
A new alpha `configuredSharedTree` had been added. | ||
This allows providing configuration options, primarily for debugging, testing and evaluation of upcoming features. | ||
The resulting configured `SharedTree` object can then be used in-place of the regular `SharedTree` imported from `fluid-framework`. | ||
|
||
```typescript | ||
import { | ||
ForestType, | ||
TreeCompressionStrategy, | ||
configuredSharedTree, | ||
typeboxValidator, | ||
} from "@fluid-framework/alpha"; | ||
// Maximum debuggability and validation enabled: | ||
const SharedTree = configuredSharedTree({ | ||
forest: ForestType.Expensive, | ||
jsonValidator: typeboxValidator, | ||
treeEncodeType: TreeCompressionStrategy.Uncompressed, | ||
}); | ||
// Opts into the under development optimized tree storage planned to be the eventual default implementation: | ||
const SharedTree = configuredSharedTree({ | ||
forest: ForestType.Optimized, | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
* Licensed under the MIT License. | ||
*/ | ||
|
||
import { assert } from "@fluidframework/core-utils/internal"; | ||
import { assert, unreachableCase } from "@fluidframework/core-utils/internal"; | ||
import type { | ||
IChannelAttributes, | ||
IChannelFactory, | ||
|
@@ -16,10 +16,12 @@ import { UsageError } from "@fluidframework/telemetry-utils/internal"; | |
|
||
import { type ICodecOptions, noopValidator } from "../codec/index.js"; | ||
import { | ||
type IEditableForest, | ||
type JsonableTree, | ||
RevisionTagCodec, | ||
type TreeStoredSchema, | ||
TreeStoredSchemaRepository, | ||
type TreeStoredSchemaSubscription, | ||
makeDetachedFieldIndex, | ||
moveToDetachedField, | ||
} from "../core/index.js"; | ||
|
@@ -66,6 +68,7 @@ import { | |
createTreeCheckout, | ||
} from "./treeCheckout.js"; | ||
import { breakingClass, throwIfBroken } from "../util/index.js"; | ||
import type { IIdCompressor } from "@fluidframework/id-compressor"; | ||
|
||
/** | ||
* Copy of data from an {@link ISharedTree} at some point in time. | ||
|
@@ -149,6 +152,27 @@ function getCodecVersions(formatVersion: number): ExplicitCodecVersions { | |
return versions; | ||
} | ||
|
||
export function buildConfiguredForest( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This refactor, and splitting out ForestOptions do not strictly have to be part of this change, but are required for the intended use of some of these APIs in #22566 , and seems small and related enough to include here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docs? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
type: ForestType, | ||
schema: TreeStoredSchemaSubscription, | ||
idCompressor: IIdCompressor, | ||
): IEditableForest { | ||
switch (type) { | ||
case ForestType.Optimized: | ||
return buildChunkedForest( | ||
makeTreeChunker(schema, defaultSchemaPolicy), | ||
undefined, | ||
idCompressor, | ||
); | ||
case ForestType.Reference: | ||
return buildForest(); | ||
case ForestType.Expensive: | ||
return buildForest(undefined, true); | ||
default: | ||
unreachableCase(type); | ||
} | ||
} | ||
|
||
/** | ||
* Shared tree, configured with a good set of indexes and field kinds which will maintain compatibility over time. | ||
* | ||
|
@@ -181,16 +205,7 @@ export class SharedTree | |
const options = { ...defaultSharedTreeOptions, ...optionsParam }; | ||
const codecVersions = getCodecVersions(options.formatVersion); | ||
const schema = new TreeStoredSchemaRepository(); | ||
const forest = | ||
options.forest === ForestType.Optimized | ||
? buildChunkedForest( | ||
makeTreeChunker(schema, defaultSchemaPolicy), | ||
undefined, | ||
runtime.idCompressor, | ||
) | ||
: options.forest === ForestType.Reference | ||
? buildForest() | ||
: buildForest(undefined, true); | ||
const forest = buildConfiguredForest(options.forest, schema, runtime.idCompressor); | ||
const revisionTagCodec = new RevisionTagCodec(runtime.idCompressor); | ||
const removedRoots = makeDetachedFieldIndex( | ||
"repair", | ||
|
@@ -348,7 +363,7 @@ export function getBranch(treeOrView: ITree | TreeView<ImplicitFieldSchema>): Tr | |
* Format versions supported by SharedTree. | ||
* | ||
* Each version documents a required minimum version of the \@fluidframework/tree package. | ||
* @internal | ||
* @alpha | ||
*/ | ||
export const SharedTreeFormatVersion = { | ||
/** | ||
|
@@ -374,26 +389,34 @@ export const SharedTreeFormatVersion = { | |
* Format versions supported by SharedTree. | ||
* | ||
* Each version documents a required minimum version of the \@fluidframework/tree package. | ||
* @internal | ||
* @alpha | ||
* @privateRemarks | ||
* See packages/dds/tree/docs/main/compatibility.md for information on how to add support for a new format. | ||
*/ | ||
export type SharedTreeFormatVersion = typeof SharedTreeFormatVersion; | ||
|
||
/** | ||
* @internal | ||
* Configuration options for SharedTree. | ||
* @alpha | ||
*/ | ||
export type SharedTreeOptions = Partial<ICodecOptions> & | ||
Partial<SharedTreeFormatOptions> & { | ||
/** | ||
* The {@link ForestType} indicating which forest type should be created for the SharedTree. | ||
*/ | ||
forest?: ForestType; | ||
}; | ||
Partial<SharedTreeFormatOptions> & | ||
ForestOptions; | ||
|
||
/** | ||
* Configuration options for SharedTree's internal tree storage. | ||
* @alpha | ||
*/ | ||
export interface ForestOptions { | ||
/** | ||
* The {@link ForestType} indicating which forest type should be created for the SharedTree. | ||
*/ | ||
readonly forest?: ForestType; | ||
} | ||
|
||
/** | ||
* Options for configuring the persisted format SharedTree uses. | ||
* @internal | ||
* @alpha | ||
*/ | ||
export interface SharedTreeFormatOptions { | ||
/** | ||
|
@@ -417,7 +440,7 @@ export interface SharedTreeFormatOptions { | |
|
||
/** | ||
* Used to distinguish between different forest types. | ||
* @internal | ||
* @alpha | ||
*/ | ||
export enum ForestType { | ||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we default to V3 (thus dubbing it our actual "V1") and that we do not support documents in V1 (and maybe V2?), how would you feel about only exposing V3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My instinct is this is a foot-gun, otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I think we should just expose a single framework wide enum which lists every framework minor version which had an opt in compat impacting change, and its value of v2.0 would map to v3 in our internal format numbers.
Fixing that is mostly orthogonal to this change.
That said, if someone has legacy documents (from before 2.0), and wants to generate test documents so they can ensure their old production documents will continue to work, these extra option might be useful to them.
Since this is just alpha, I think we can sort out these details later, but I do agree this isn't want we want long term and/or when this goes public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that we haven't done the work needed to create separate public vs internal configuration, but as long as these are targeted at alpha / debugging usage I think it may be better to keep using the internal types here rather than adding all the complexity needed to create distinct public API configuration, at least for now.
I have added a TODO to the APi's private remarks. I'll let API reviewers decide if they want to block exposing these as alpha on that work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if you set this to V1? Do we support writing legacy documents (which are immediately broken/unsupported)? I thought we only support writing N and N-1.
I'll agree that allowing V2 writing seems fine for the (possibly nonexistent) customers that want to test support for that, but exposing V1 at all seems very strange to me. @noencke thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(regardless, I did approve and don't think this needs to block this since it's alpha)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't support V1 then I don't see why we'd expose V1, but exposing V2 makes sense for now, particularly since this is alpha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we leave some of the context from this discussion in
@privateRemarks
in the code for future reference?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there something more you want beyond what's already in fe8daec ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, no, I didn't see that. Looks good to me!