Contents
🌳 SharedTree DDS Changes
New alpha APIs for schema evolution (#23362)
There are now @alpha
APIs for schema evolution which support adding optional fields to object node types without a staged rollout.
SharedTree has many safety checks in place to ensure applications understand the format of documents they must support. One of these checks verifies that the view schema (defined in application's code) aligns with the document schema (determined by the document data at rest). This helps to ensure that clients running incompatible versions of the application's code don't collaborate at the same time on some document, which could cause data loss or disrupt application invariants. One general solution application authors can perform is to stage the rollout of a feature which changes document schema into multiple phases:
- Release an application version which understands documents written with the new format but doesn't attempt to upgrade any documents
- Wait for this application version to saturate in the app's ecosystem
- Release an application version which upgrades documents to start leveraging the new format.
However, this process can be cumbersome for application authors: for many types of changes, an app author doesn't particularly care if older application code collaborates with newer code, as the only downside is that the older application version might not present a fully faithful experience. As an example, consider an application which renders circles on a canvas (similar to what is presented here). The application author might anticipate adding support to render the circle with various different other properties (border style, border width, background color, varying radius, etc.). Therefore, they should declare their schema using SchemaFactoryObjectOptions.allowUnknownOptionalFields
like so:
import { SchemaFactoryAlpha } from "@fluidframework/tree/alpha";
// "Old" application code/schema
const factory = new SchemaFactoryAlpha("Geometry");
class Circle extends factory.object(
"Circle",
{
x: factory.number,
y: factory.number,
},
{ allowUnknownOptionalFields: true },
) {}
Later, they add some of these features to their application:
import { SchemaFactoryAlpha } from "@fluidframework/tree/alpha";
// "New" application code/schema
const factory = new SchemaFactoryAlpha("Geometry");
class Circle extends factory.object(
"Circle",
{
x: factory.number,
y: factory.number,
// Note that radius and color must both be declared as optional fields since this application must
// support opening up existing documents that didn't have this information.
radius: factory.optional(factory.number),
color: factory.optional(factory.string), // ex: #00FF00
},
{ allowUnknownOptionalFields: true },
) {}
When they go to deploy this newer version of the application, they could opt to start upgrading documents as soon as the newer code is rolled out, and the older code would still be able to open up (and collaborate on) documents using the newer schema version. Note that it's only important that the old application code elected to allow opening documents with unknown optional fields. This policy is not persisted into documents in any form, so applications are free to modify it at any point.
For specific API details, see documentation on SchemaFactoryObjectOptions.allowUnknownOptionalFields
. For a more thorough discussion of this topic, see Schema Evolvability in the SharedTree README.
Change details
Commit: 2406e00
Affected packages:
- @fluidframework/tree
- fluid-framework
Metadata can be associated with Node Schema (#23321)
Users of TreeView can now specify metadata when creating Node Schema, via SchemaFactoryAlpha
. This metadata may include system-understood properties like description
.
Example:
const schemaFactory = new SchemaFactoryAlpha(...);
class Point extends schemaFactory.object("Point", {
x: schemaFactory.required(schemaFactory.number),
y: schemaFactory.required(schemaFactory.number),
},
{
metadata: {
description: "A point in 2D space",
},
}) {}
Functionality like the experimental conversion of Tree Schema to JSON Schema (getJsonSchema) leverages such system-understood metadata to generate useful information. In the case of the description
property, it is mapped directly to the description
property supported by JSON Schema.
Custom, user-defined properties can also be specified. These properties will not be used by the system by default, but can be used to associate common application-specific properties with Node Schema.
SchemaFactoryAlpha
Updates
object
andobjectRecursive
,arrayRecursive
, andmapRecursive
now supportmetadata
in theiroptions
parameter.- (new)
arrayAlpha
- Variant ofarray
that accepts an options parameter which supportsmetadata
- (new)
mapAlpha
- Variant ofmap
that accepts an options parameter which supportsmetadata
Example
An application is implementing search functionality. By default, the app author wishes for all app content to be potentially indexable by search, unless otherwise specified. They can leverage schema metadata to decorate types of nodes that should be ignored by search, and leverage that information when walking the tree during a search.
interface AppMetadata {
/**
* Whether or not nodes of this type should be ignored by search.
* @defaultValue `false`
*/
searchIgnore?: boolean;
}
const schemaFactory = new SchemaFactoryAlpha(...);
class Point extends schemaFactory.object("Point", {
x: schemaFactory.required(schemaFactory.number),
y: schemaFactory.required(schemaFactory.number),
},
{
metadata: {
description: "A point in 2D space",
custom: {
searchIgnore: true,
},
}
}) {}
Search can then be implemented to look for the appropriate metadata, and leverage it to omit the unwanted position data from search.
Potential for breaking existing code
These changes add the new property "metadata" to the base type from which all node schema derive. If you have existing node schema subclasses that include a property of this name, there is a chance for potential conflict here that could be breaking. If you encounter issues here, consider renaming your property or leveraging the new metadata support.
Change details
Commit: 58619c3
Affected packages:
- @fluidframework/tree
- fluid-framework
🛠️ Start Building Today!
Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!