Skip to content

Commit

Permalink
tree: More schema cleanup (microsoft#22322)
Browse files Browse the repository at this point in the history
## Description

Reduce use of SchemaBuilderInternal.

Fix missing sort when persisting field schema found while editing test
schema: this is not a correctness issue, but should improve consistency
and thus blob reuse in the encoded format.
  • Loading branch information
CraigMacomber authored Aug 27, 2024
1 parent c3f64a9 commit 961c9e8
Show file tree
Hide file tree
Showing 18 changed files with 226 additions and 271 deletions.
3 changes: 2 additions & 1 deletion packages/dds/tree/src/core/schema-stored/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ function decodeValueSchema(inMemory: PersistedValueSchema): ValueSchema {
export function encodeFieldSchema(schema: TreeFieldStoredSchema): FieldSchemaFormat {
return {
kind: schema.kind,
types: [...schema.types],
// Types are sorted by identifier to improve stability of persisted data to increase chance of schema blob reuse.
types: [...schema.types].sort(),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
checkoutWithContent,
cursorFromInsertableTreeField,
flexTreeViewWithContent,
forestWithContent,
numberSequenceRootSchema,
testIdCompressor,
} from "../../utils.js";
Expand Down Expand Up @@ -206,13 +207,13 @@ describe("End to end chunked encoding", () => {
const chunk = new UniformChunk(numberShape.withTopLevelLength(4), [1, 2, 3, 4]);
assert(!chunk.isShared());

const flexTree = flexTreeViewWithContent({
const forest = forestWithContent({
schema: numberSequenceRootSchema,
initialTree: chunk.cursor(),
});

const forestSummarizer = new ForestSummarizer(
flexTree.context.checkout.forest as IEditableForest,
forest,
revisionTagCodec,
fieldBatchCodec,
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
*/

import { storedEmptyFieldSchema } from "../../../core/index.js";
import { intoStoredSchema } from "../../../feature-libraries/index.js";
import {
encodeTreeSchema,
// eslint-disable-next-line import/no-internal-modules
} from "../../../feature-libraries/schema-index/schemaSummarizer.js";
import { toStoredSchema } from "../../../simple-tree/index.js";
import { takeJsonSnapshot, useSnapshotDirectory } from "../../snapshots/index.js";
import { jsonSequenceRootSchema } from "../../utils.js";
import { JsonUnion } from "../../utils.js";

describe("schemaSummarizer", () => {
describe("encodeTreeSchema", () => {
Expand All @@ -24,7 +24,7 @@ describe("schemaSummarizer", () => {
});

it("simple encoded schema", () => {
const encoded = encodeTreeSchema(intoStoredSchema(jsonSequenceRootSchema));
const encoded = encodeTreeSchema(toStoredSchema(JsonUnion));
takeJsonSnapshot(encoded);
});
});
Expand Down
71 changes: 71 additions & 0 deletions packages/dds/tree/src/test/sequenceRootUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*!
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
* Licensed under the MIT License.
*/

import {
type TreeStoredSchema,
rootFieldKey,
type MapTree,
type TreeNodeSchemaIdentifier,
} from "../core/index.js";
import { leaf, singleJsonCursor } from "../domains/index.js";
import { FieldKinds, cursorForMapTreeField } from "../feature-libraries/index.js";
import type { ITreeCheckout } from "../shared-tree/index.js";
import { toStoredSchema } from "../simple-tree/index.js";
import { brand, type JsonCompatible } from "../util/index.js";
import { checkoutWithContent, JsonUnion } from "./utils.js";
// eslint-disable-next-line import/no-internal-modules
import { normalizeAllowedTypes } from "../simple-tree/schemaTypes.js";

// This file provides utilities for testing sequence fields using documents where the root is the sequence being tested.
// This pattern is not expressible using the public simple-tree API, and is only for testing internal details.

const rootJsonSequenceSchema: TreeStoredSchema = {
nodeSchema: toStoredSchema(JsonUnion).nodeSchema,
rootFieldSchema: {
kind: FieldKinds.sequence.identifier,
types: new Set(
[...normalizeAllowedTypes(JsonUnion)].map((s) =>
brand<TreeNodeSchemaIdentifier>(s.identifier),
),
),
},
};

/**
* Helper function to insert node at a given index.
*
* @param tree - The tree on which to perform the insert.
* @param index - The index in the root field at which to insert.
* @param value - The value of the inserted nodes.
*/
export function insert(tree: ITreeCheckout, index: number, ...values: string[]): void {
const fieldEditor = tree.editor.sequenceField({ field: rootFieldKey, parent: undefined });
fieldEditor.insert(
index,
cursorForMapTreeField(
values.map((value): MapTree => ({ fields: new Map(), type: leaf.string.name, value })),
),
);
}

/**
* Removes `count` items from the root field of `tree`.
*/
export function remove(tree: ITreeCheckout, index: number, count: number): void {
const field = tree.editor.sequenceField({ parent: undefined, field: rootFieldKey });
field.remove(index, count);
}

/**
* Creates a sequence field at the root.
*/
export function makeTreeFromJsonSequence(json: JsonCompatible[]): ITreeCheckout {
const cursors = json.map(singleJsonCursor);
const tree = checkoutWithContent({
schema: rootJsonSequenceSchema,
initialTree: cursors,
});
return tree;
}
Loading

0 comments on commit 961c9e8

Please sign in to comment.