Skip to content

Commit bffbb3b

Browse files
Adds No Change constraint to SharedTree (#26059)
This change implements the No Change constraint in SharedTree for the table support effort. To implement this constraint, we: 1 - Added a new EncodedModularChangesetV2 type i - This also required us to refactor EncodedModularChangeset by renaming it to EncodedModularChangesetV1 and exporting a couple more types from that file for reuse by EncodedModularChangesetV2 ii - Lightly refactored modular changeset codec to handle codec versions iii - Created new versions for related codecs to use the new encoded modular changeset 2 - Added a new TransactionConstraint, named NoChangeConstraint, to the public API i - Since the new constraint is an alpha API, we couldn't union it directly onto the preexisting TransactionConstraint type (which is public), this PR adds a new TransactionConstraintAlpha type which includes NoChangeConstraint ii - Update SharedTree alpha APIs which used to use TransactionConstraints use TransactionConstraintAlpha --------- Co-authored-by: yann-achard-MS <97201204+yann-achard-MS@users.noreply.github.com>
1 parent 5990e7b commit bffbb3b

89 files changed

Lines changed: 17408 additions & 625 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/dds/tree/api-report/tree.alpha.api.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ export const FluidClientVersion: {
362362
readonly v2_52: "2.52.0";
363363
readonly v2_73: "2.73.0";
364364
readonly v2_74: "2.74.0";
365+
readonly v2_80: "2.80.0";
365366
};
366367

367368
// @beta
@@ -736,6 +737,12 @@ export const MapNodeSchema: {
736737
readonly [Symbol.hasInstance]: (value: TreeNodeSchema) => value is MapNodeSchema;
737738
};
738739

740+
// @alpha
741+
export interface NoChangeConstraint {
742+
// (undocumented)
743+
readonly type: "noChange";
744+
}
745+
739746
// @public @system
740747
type NodeBuilderData<T extends TreeNodeSchemaCore<string, NodeKind, boolean>> = T extends TreeNodeSchemaCore<string, NodeKind, boolean, unknown, infer TBuild> ? TBuild : never;
741748

@@ -926,7 +933,7 @@ export interface RunTransaction {
926933

927934
// @alpha @input
928935
export interface RunTransactionParams {
929-
readonly preconditions?: readonly TransactionConstraint[];
936+
readonly preconditions?: readonly TransactionConstraintAlpha[];
930937
}
931938

932939
// @public @sealed
@@ -1389,12 +1396,15 @@ export type TransactionCallbackStatus<TSuccessValue, TFailureValue> = ({
13891396
rollback: true;
13901397
value: TFailureValue;
13911398
}) & {
1392-
preconditionsOnRevert?: readonly TransactionConstraint[];
1399+
preconditionsOnRevert?: readonly TransactionConstraintAlpha[];
13931400
};
13941401

13951402
// @public
13961403
export type TransactionConstraint = NodeInDocumentConstraint;
13971404

1405+
// @alpha @sealed
1406+
export type TransactionConstraintAlpha = TransactionConstraint | NoChangeConstraint;
1407+
13981408
// @alpha
13991409
export type TransactionResult = Omit<TransactionResultSuccess<unknown>, "value"> | Omit<TransactionResultFailed<unknown>, "value">;
14001410

packages/dds/tree/src/codec/codec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,17 @@ export const FluidClientVersion = {
577577
* - ForestSummaryFormatVersion.v3 - written when minVersionForCollab \>= 2.74
578578
*/
579579
v2_74: "2.74.0",
580+
581+
/**
582+
* Fluid Framework Client 2.80 and newer.
583+
* @remarks
584+
* New formats introduced in 2.80:
585+
* - MessageFormatVersion.v6 - written when minVersionForCollab \>= 2.80
586+
* - EditManagerFormatVersion.v6 - written when minVersionForCollab \>= 2.80
587+
* - SharedTreeChangeFormatVersion.v5 - written when minVersionForCollab \>= 2.80
588+
* - ModularChangeFormatVersion.v5 - written when minVersionForCollab \>= 2.80
589+
*/
590+
v2_80: "2.80.0",
580591
} as const satisfies Record<string, MinimumVersionForCollab>;
581592

582593
/**

packages/dds/tree/src/feature-libraries/default-schema/defaultEditBuilder.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { assert, oob } from "@fluidframework/core-utils/internal";
77
import { UsageError } from "@fluidframework/telemetry-utils/internal";
88

9-
import type { ICodecFamily } from "../../codec/index.js";
9+
import type { CodecWriteOptions, ICodecFamily } from "../../codec/index.js";
1010
import {
1111
type ChangeAtomId,
1212
type ChangeEncodingContext,
@@ -58,8 +58,11 @@ export class DefaultChangeFamily
5858
{
5959
private readonly modularFamily: ModularChangeFamily;
6060

61-
public constructor(codecs: ICodecFamily<ModularChangeset, ChangeEncodingContext>) {
62-
this.modularFamily = new ModularChangeFamily(fieldKinds, codecs);
61+
public constructor(
62+
codecs: ICodecFamily<ModularChangeset, ChangeEncodingContext>,
63+
codecOptions: CodecWriteOptions,
64+
) {
65+
this.modularFamily = new ModularChangeFamily(fieldKinds, codecs, codecOptions);
6366
}
6467

6568
public get rebaser(): ChangeRebaser<DefaultChangeset> {
@@ -74,7 +77,12 @@ export class DefaultChangeFamily
7477
mintRevisionTag: () => RevisionTag,
7578
changeReceiver: (change: TaggedChange<DefaultChangeset>) => void,
7679
): DefaultEditBuilder {
77-
return new DefaultEditBuilder(this, mintRevisionTag, changeReceiver);
80+
return new DefaultEditBuilder(
81+
this,
82+
mintRevisionTag,
83+
changeReceiver,
84+
this.modularFamily.codecOptions,
85+
);
7886
}
7987
}
8088

@@ -161,16 +169,26 @@ export interface IDefaultEditBuilder<TContent = TreeChunk> {
161169
): void;
162170

163171
/**
164-
* Add a constraint that the node at the given path must exist.
172+
* Add a constraint that, for this change to apply, the node at the given path must exist immediately before the change is applied.
165173
* @param path - The path to the node that must exist.
166174
*/
167175
addNodeExistsConstraint(path: NormalizedUpPath): void;
168176

169177
/**
170-
* Add a constraint that the node at the given path must exist when reverting a change.
178+
* Add a constraint that, for the revert of this change to apply, the node at the given path must exist immediately before the revert is applied.
171179
* @param path - The path to the node that must exist when reverting a change.
172180
*/
173181
addNodeExistsConstraintOnRevert(path: NormalizedUpPath): void;
182+
183+
/**
184+
* Add a constraint that, for this change to apply, the document must be in the same state immediately before this change is applied as it was before this change was authored.
185+
*/
186+
addNoChangeConstraint(): void;
187+
188+
/**
189+
* Add a constraint that, for the revert of this change to apply, the document must be in the same state immediately before the revert is applied as it was after this change was applied.
190+
*/
191+
addNoChangeConstraintOnRevert(): void;
174192
}
175193

176194
/**
@@ -184,8 +202,14 @@ export class DefaultEditBuilder implements ChangeFamilyEditor, IDefaultEditBuild
184202
family: ChangeFamily<ChangeFamilyEditor, DefaultChangeset>,
185203
private readonly mintRevisionTag: () => RevisionTag,
186204
changeReceiver: (change: TaggedChange<DefaultChangeset>) => void,
205+
codecOptions: CodecWriteOptions,
187206
) {
188-
this.modularBuilder = new ModularEditBuilder(family, fieldKinds, changeReceiver);
207+
this.modularBuilder = new ModularEditBuilder(
208+
family,
209+
fieldKinds,
210+
changeReceiver,
211+
codecOptions,
212+
);
189213
}
190214

191215
public enterTransaction(): void {
@@ -203,6 +227,14 @@ export class DefaultEditBuilder implements ChangeFamilyEditor, IDefaultEditBuild
203227
this.modularBuilder.addNodeExistsConstraintOnRevert(path, this.mintRevisionTag());
204228
}
205229

230+
public addNoChangeConstraint(): void {
231+
this.modularBuilder.addNoChangeConstraint(this.mintRevisionTag());
232+
}
233+
234+
public addNoChangeConstraintOnRevert(): void {
235+
this.modularBuilder.addNoChangeConstraintOnRevert(this.mintRevisionTag());
236+
}
237+
206238
public valueField(field: FieldUpPath): ValueFieldEditBuilder<TreeChunk> {
207239
return {
208240
set: (newContent: TreeChunk): void => {

packages/dds/tree/src/feature-libraries/default-schema/defaultFieldKinds.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,19 @@ export const fieldKindConfigurations: ReadonlyMap<
202202
[identifier.identifier, { kind: identifier, formatVersion: 1 }],
203203
]),
204204
],
205+
[
206+
brand(5),
207+
new Map<FieldKindIdentifier, FieldKindConfigurationEntry>([
208+
[required.identifier, { kind: required, formatVersion: 2 }],
209+
[optional.identifier, { kind: optional, formatVersion: 2 }],
210+
[sequence.identifier, { kind: sequence, formatVersion: 3 }],
211+
[forbidden.identifier, { kind: forbidden, formatVersion: 1 }],
212+
[identifier.identifier, { kind: identifier, formatVersion: 1 }],
213+
]),
214+
],
205215
]);
206216

207-
export type ModularChangeFormatVersion = Brand<3 | 4, "ModularChangeFormatVersion">;
217+
export type ModularChangeFormatVersion = Brand<3 | 4 | 5, "ModularChangeFormatVersion">;
208218
export function getCodecTreeForModularChangeFormat(
209219
version: ModularChangeFormatVersion,
210220
): CodecTree {

packages/dds/tree/src/feature-libraries/default-schema/mappedEditBuilder.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,10 @@ export class MappedEditBuilder<TBase, TAdapted> implements IDefaultEditBuilder<T
6666
public addNodeExistsConstraintOnRevert(path: NormalizedUpPath): void {
6767
this.baseBuilder.addNodeExistsConstraintOnRevert(path);
6868
}
69+
public addNoChangeConstraint(): void {
70+
this.baseBuilder.addNoChangeConstraint();
71+
}
72+
public addNoChangeConstraintOnRevert(): void {
73+
this.baseBuilder.addNoChangeConstraintOnRevert();
74+
}
6975
}

packages/dds/tree/src/feature-libraries/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ export {
8080
type NodeExistsConstraint,
8181
ModularChangeFamily,
8282
type RelevantRemovedRootsFromChild,
83-
EncodedModularChangeset,
83+
EncodedModularChangesetV1,
84+
EncodedModularChangesetV2,
8485
updateRefreshers,
8586
type NodeId,
8687
type FieldChangeEncodingContext,

packages/dds/tree/src/feature-libraries/modular-schema/fieldChangeHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import type {
1919
import type { IdAllocator, Invariant } from "../../util/index.js";
2020

2121
import type { CrossFieldManager } from "./crossFieldQueries.js";
22-
import type { EncodedNodeChangeset } from "./modularChangeFormat.js";
22+
import type { EncodedNodeChangeset } from "./modularChangeFormatV1.js";
2323
import type { CrossFieldKeyRange, NodeId } from "./modularChangeTypes.js";
2424

2525
export type NestedChangesIndices = [

packages/dds/tree/src/feature-libraries/modular-schema/genericFieldKindCodecs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { type ICodecFamily, type IJsonCodec, makeCodecFamily } from "../../codec
88
import type { FieldChangeEncodingContext } from "./fieldChangeHandler.js";
99
import { EncodedGenericChangeset } from "./genericFieldKindFormat.js";
1010
import { newGenericChangeset, type GenericChangeset } from "./genericFieldKindTypes.js";
11-
import { EncodedNodeChangeset } from "./modularChangeFormat.js";
11+
import { EncodedNodeChangeset } from "./modularChangeFormatV1.js";
1212

1313
export function makeGenericChangeCodec(): ICodecFamily<
1414
GenericChangeset,

packages/dds/tree/src/feature-libraries/modular-schema/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ export {
2323
ChangesetLocalIdSchema,
2424
EncodedChangeAtomId,
2525
EncodedRevisionInfo,
26-
EncodedModularChangeset,
26+
EncodedModularChangesetV1,
2727
EncodedNodeChangeset,
28-
} from "./modularChangeFormat.js";
28+
} from "./modularChangeFormatV1.js";
29+
export { EncodedModularChangesetV2 } from "./modularChangeFormatV2.js";
2930
export { FlexFieldKind, type FullSchemaPolicy } from "./fieldKind.js";
3031
export {
3132
type FieldChangeHandler,
@@ -52,6 +53,7 @@ export type {
5253
FieldChangeset,
5354
HasFieldChanges,
5455
ModularChangeset,
56+
NoChangeConstraint,
5557
NodeExistsConstraint,
5658
NodeId,
5759
} from "./modularChangeTypes.js";

0 commit comments

Comments
 (0)