|
| 1 | +<!-- THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. --> |
| 2 | + |
| 3 | +# Fluid Framework v2.73.0 |
| 4 | + |
| 5 | +## Contents |
| 6 | + |
| 7 | +- [🌳 SharedTree DDS Changes](#-sharedtree-dds-changes) |
| 8 | + - [Schema snapshot compatibility checker (#25861)](#schema-snapshot-compatibility-checker-25861) |
| 9 | + |
| 10 | +## 🌳 SharedTree DDS Changes |
| 11 | + |
| 12 | +### Schema snapshot compatibility checker ([#25861](https://github.com/microsoft/FluidFramework/issues/25861)) |
| 13 | + |
| 14 | +This change adds alpha APIs for creating snapshots of view schema and testing their compatibility for the purposes of schema migrations. |
| 15 | + |
| 16 | +New APIs: |
| 17 | + |
| 18 | +- `checkCompatibility` - Checks the compatibility of the view schema which created the document against the view schema being used to open it. |
| 19 | +- `importCompatibilitySchemaSnapshot` - Parse a JSON representation of a tree schema into a concrete schema. |
| 20 | +- `exportCompatibilitySchemaSnapshot` - Returns a JSON representation of the tree schema for snapshot compatibility checking. |
| 21 | + |
| 22 | +#### Example: Current view schema vs. historical view schema |
| 23 | + |
| 24 | +An application author is developing an app that has a schema for storing 2D Points. They wish to maintain backwards compatibility in future versions and avoid changing their view schema in a way that breaks this behavior. When introducing a new initial schema, they persists a snapshot using `exportCompatibilitySchemaSnapshot`: |
| 25 | + |
| 26 | +```ts |
| 27 | +const factory = new SchemaFactory("test"); |
| 28 | + |
| 29 | +// The past view schema, for the purposes of illustration. This wouldn't normally appear as a concrete schema in the test |
| 30 | +// checking compatibility, but rather would be loaded from a snapshot. |
| 31 | +class Point2D extends factory.object("Point", { |
| 32 | + x: factory.number, |
| 33 | + y: factory.number, |
| 34 | +}) {} |
| 35 | +const viewSchema = new TreeViewConfiguration({ schema: Point2D }); |
| 36 | +const encodedSchema = JSON.stringify( |
| 37 | + exportCompatibilitySchemaSnapshot(viewSchema), |
| 38 | +); |
| 39 | +fs.writeFileSync("PointSchema.json", encodedSchema); |
| 40 | +``` |
| 41 | + |
| 42 | +Next they create a regression test to ensure that the current view schema can read content written by the original view schema (`SchemaCompatibilityStatus.canUpgrade`). Initially `currentViewSchema === Point2D`: |
| 43 | + |
| 44 | +```ts |
| 45 | +const encodedSchema = JSON.parse(fs.readFileSync("PointSchema.json", "utf8")); |
| 46 | +const oldViewSchema = importCompatibilitySchemaSnapshot(encodedSchema); |
| 47 | + |
| 48 | +// Check to see if the document created by the historical view schema can be opened with the current view schema |
| 49 | +const compatibilityStatus = checkCompatibility( |
| 50 | + oldViewSchema, |
| 51 | + currentViewSchema, |
| 52 | +); |
| 53 | + |
| 54 | +// Check to see if the document created by the historical view schema can be opened with the current view schema |
| 55 | +const backwardsCompatibilityStatus = checkCompatibility( |
| 56 | + oldViewSchema, |
| 57 | + currentViewSchema, |
| 58 | +); |
| 59 | + |
| 60 | +// z is not present in Point2D, so the schema must be upgraded |
| 61 | +assert.equal(backwardsCompatibilityStatus.canView, false); |
| 62 | + |
| 63 | +// The schema can be upgraded to add the new optional field |
| 64 | +assert.equal(backwardsCompatibilityStatus.canUpgrade, true); |
| 65 | +``` |
| 66 | + |
| 67 | +Additionally, they a regression test to ensure that older view schemas can read content written by the current view schema (`SchemaCompatibilityStatus.canView`): |
| 68 | + |
| 69 | +```ts |
| 70 | +// Test what the old version of the application would do with a tree using the new schema: |
| 71 | +const forwardsCompatibilityStatus = checkCompatibility( |
| 72 | + currentViewSchema, |
| 73 | + oldViewSchema, |
| 74 | +); |
| 75 | + |
| 76 | +// If the old schema set allowUnknownOptionalFields, this would be true, but since it did not, |
| 77 | +// this assert will fail, detecting the forwards compatibility break: |
| 78 | +// this means these two versions of the application cannot collaborate on content using these schema. |
| 79 | +assert.equal(forwardsCompatibilityStatus.canView, true); |
| 80 | +``` |
| 81 | + |
| 82 | +Later in the application development cycle, the application author decides they want to change their Point2D to a Point3D, adding an extra field: |
| 83 | + |
| 84 | +```ts |
| 85 | +// Build the current view schema |
| 86 | +const schemaFactory = new SchemaFactory("test"); |
| 87 | +class Point3D extends schemaFactory.object("Point", { |
| 88 | + x: factory.number, |
| 89 | + y: factory.number, |
| 90 | + |
| 91 | + // The current schema has a new optional field that was not present on Point2D |
| 92 | + z: factory.optional(factory.number), |
| 93 | +}) {} |
| 94 | +``` |
| 95 | + |
| 96 | +The test first compatibility test will pass as the Point2D schema is upgradeable to a Point3D schema. However, the second compatibility test fill fail as an application using the Point2D view schema cannot collaborate on content authored using the Point3D schema. |
| 97 | + |
| 98 | +#### Change details |
| 99 | + |
| 100 | +Commit: [`e5be416`](https://github.com/microsoft/FluidFramework/commit/e5be4163210ef68b7f8a7c10502f4871c30ec9f3) |
| 101 | + |
| 102 | +Affected packages: |
| 103 | + |
| 104 | +- @fluidframework/tree |
| 105 | +- fluid-framework |
| 106 | + |
| 107 | +[⬆️ Table of contents](#contents) |
| 108 | + |
| 109 | +### 🛠️ Start Building Today! |
| 110 | + |
| 111 | +Please continue to engage with us on GitHub [Discussion](https://github.com/microsoft/FluidFramework/discussions) and [Issue](https://github.com/microsoft/FluidFramework/issues) pages as you adopt Fluid Framework! |
0 commit comments