Skip to content

Commit

Permalink
MergeTree Client Legacy API Removed (#22697)
Browse files Browse the repository at this point in the history
The `Client` class in the merge-tree package has been removed.
Additionally, types that directly or indirectly expose the merge-tree
`Client` class have also been removed.

The removed types were not meant to be used directly, and direct usage
was not supported:

- AttributionPolicy
- IClientEvents
- IMergeTreeAttributionOptions
- SharedSegmentSequence
- SharedStringClass

Some classes that referenced the `Client` class have been transitioned
to interfaces. Direct instantiation of these classes was not supported
or necessary for any supported scenario, so the change to an interface
should not impact usage. This applies to the following types:

- SequenceInterval
- SequenceEvent
- SequenceDeltaEvent
- SequenceMaintenanceEvent

The initial deprecations of the now changed or removed types were
announced in Fluid Framework v2.4.0:
[Several MergeTree Client Legacy APIs are now
deprecated](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.4.0.md#several-mergetree-client-legacy-apis-are-now-deprecated-22629)

---------

Co-authored-by: Tyler Butler <[email protected]>
  • Loading branch information
anthony-murphy and tylerbutler authored Nov 5, 2024
1 parent 99fbaf4 commit 2aa0b5e
Show file tree
Hide file tree
Showing 26 changed files with 480 additions and 570 deletions.
30 changes: 30 additions & 0 deletions .changeset/rude-views-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
"fluid-framework": minor
"@fluidframework/merge-tree": minor
"@fluidframework/sequence": minor
---
---
"section": deprecation
---

MergeTree `Client` Legacy API Removed

The `Client` class in the merge-tree package has been removed. Types that directly or indirectly expose the merge-tree `Client` class have also been removed.

The removed types were not meant to be used directly, and direct usage was not supported:

- AttributionPolicy
- IClientEvents
- IMergeTreeAttributionOptions
- SharedSegmentSequence
- SharedStringClass

Some classes that referenced the `Client` class have been transitioned to interfaces. Direct instantiation of these classes was not supported or necessary for any supported scenario, so the change to an interface should not impact usage. This applies to the following types:

- SequenceInterval
- SequenceEvent
- SequenceDeltaEvent
- SequenceMaintenanceEvent

The initial deprecations of the now changed or removed types were announced in Fluid Framework v2.4.0:
[Several MergeTree Client Legacy APIs are now deprecated](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.4.0.md#several-mergetree-client-legacy-apis-are-now-deprecated-22629)
124 changes: 0 additions & 124 deletions packages/dds/merge-tree/api-report/merge-tree.legacy.alpha.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@
// @alpha
export function appendToMergeTreeDeltaRevertibles(deltaArgs: IMergeTreeDeltaCallbackArgs, revertibles: MergeTreeDeltaRevertible[]): void;

// @alpha @sealed @deprecated
export interface AttributionPolicy {
attach: (client: Client) => void;
detach: () => void;
// (undocumented)
isAttached: boolean;
serializer: IAttributionCollectionSerializer;
}

// @alpha (undocumented)
export abstract class BaseSegment implements ISegment {
constructor(properties?: PropertySet);
Expand Down Expand Up @@ -87,104 +78,6 @@ export abstract class BaseSegment implements ISegment {
wasMovedOnInsert?: boolean | undefined;
}

// @alpha @deprecated (undocumented)
export class Client extends TypedEventEmitter<IClientEvents> {
constructor(specToSegment: (spec: IJSONSegment) => ISegment, logger: ITelemetryLoggerExt, options?: IMergeTreeOptions & PropertySet, getMinInFlightRefSeq?: () => number | undefined);
// (undocumented)
addLongClientId(longClientId: string): void;
annotateMarker(marker: Marker, props: PropertySet): IMergeTreeAnnotateMsg | undefined;
annotateRangeLocal(start: number, end: number, props: PropertySet): IMergeTreeAnnotateMsg | undefined;
// (undocumented)
applyMsg(msg: ISequencedDocumentMessage, local?: boolean): void;
// (undocumented)
applyStashedOp(op: IMergeTreeOp): void;
createLocalReferencePosition(segment: ISegment | "start" | "end", offset: number | undefined, refType: ReferenceType, properties: PropertySet | undefined, slidingPreference?: SlidingPreference, canSlideToEndpoint?: boolean): LocalReferencePosition;
// (undocumented)
createTextHelper(): IMergeTreeTextHelper;
findReconnectionPosition(segment: ISegment, localSeq: number): number;
// (undocumented)
getClientId(): number;
// (undocumented)
getCollabWindow(): CollaborationWindow;
// (undocumented)
getContainingSegment<T extends ISegment>(pos: number, sequenceArgs?: Pick<ISequencedDocumentMessage, "referenceSequenceNumber" | "clientId">, localSeq?: number): {
segment: T | undefined;
offset: number | undefined;
};
// (undocumented)
getCurrentSeq(): number;
// (undocumented)
getLength(): number;
// (undocumented)
getLongClientId(shortClientId: number): string;
// (undocumented)
getMarkerFromId(id: string): ISegment | undefined;
// (undocumented)
getOrAddShortClientId(longClientId: string): number;
getPosition(segment: ISegment | undefined, localSeq?: number): number;
// (undocumented)
getPropertiesAtPosition(pos: number): PropertySet | undefined;
// (undocumented)
getRangeExtentsOfPosition(pos: number): {
posStart: number | undefined;
posAfterEnd: number | undefined;
};
// (undocumented)
protected getShortClientId(longClientId: string): number;
insertAtReferencePositionLocal(refPos: ReferencePosition, segment: ISegment): IMergeTreeInsertMsg | undefined;
insertSegmentLocal(pos: number, segment: ISegment): IMergeTreeInsertMsg | undefined;
// (undocumented)
load(runtime: IFluidDataStoreRuntime, storage: IChannelStorageService, serializer: IFluidSerializer): Promise<{
catchupOpsP: Promise<ISequencedDocumentMessage[]>;
}>;
localReferencePositionToPosition(lref: ReferencePosition): number;
// (undocumented)
localTransaction(groupOp: IMergeTreeGroupMsg): void;
// (undocumented)
readonly logger: ITelemetryLoggerExt;
// (undocumented)
longClientId: string | undefined;
obliterateRangeLocal(start: number | InteriorSequencePlace, end: number | InteriorSequencePlace): IMergeTreeObliterateMsg | IMergeTreeObliterateSidedMsg;
peekPendingSegmentGroups(): SegmentGroup | undefined;
// (undocumented)
peekPendingSegmentGroups(count: number): SegmentGroup | SegmentGroup[] | undefined;
posFromRelativePos(relativePos: IRelativePosition): number;
regeneratePendingOp(resetOp: IMergeTreeOp, segmentGroup: SegmentGroup | SegmentGroup[]): IMergeTreeOp;
removeLocalReferencePosition(lref: LocalReferencePosition): LocalReferencePosition | undefined;
removeRangeLocal(start: number, end: number): IMergeTreeRemoveMsg;
resolveRemoteClientPosition(remoteClientPosition: number, remoteClientRefSeq: number, remoteClientId: string): number | undefined;
rollback?(op: unknown, localOpMetadata: unknown): void;
searchForMarker(startPos: number, markerLabel: string, forwards?: boolean): Marker | undefined;
serializeGCData(handle: IFluidHandle, handleCollectingSerializer: IFluidSerializer): void;
// (undocumented)
readonly specToSegment: (spec: IJSONSegment) => ISegment;
// (undocumented)
startOrUpdateCollaboration(longClientId: string | undefined, minSeq?: number, currentSeq?: number): void;
// (undocumented)
summarize(runtime: IFluidDataStoreRuntime, handle: IFluidHandle, serializer: IFluidSerializer, catchUpMsgs: ISequencedDocumentMessage[]): ISummaryTreeWithStats;
// (undocumented)
updateMinSeq(minSeq: number): void;
// (undocumented)
protected walkAllSegments<TClientData>(action: (segment: ISegment, accum?: TClientData) => boolean, accum?: TClientData): boolean;
// (undocumented)
walkSegments<TClientData>(handler: ISegmentAction<TClientData>, start: number | undefined, end: number | undefined, accum: TClientData, splitRange?: boolean): void;
// (undocumented)
walkSegments(handler: ISegmentAction<undefined>, start?: number, end?: number, accum?: undefined, splitRange?: boolean): void;
}

// @alpha @deprecated (undocumented)
export class CollaborationWindow {
// (undocumented)
clientId: number;
// (undocumented)
collaborating: boolean;
currentSeq: number;
// (undocumented)
loadFrom(a: CollaborationWindow): void;
localSeq: number;
minSeq: number;
}

// @alpha
export function discardMergeTreeDeltaRevertible(revertibles: MergeTreeDeltaRevertible[]): void;

Expand Down Expand Up @@ -244,16 +137,6 @@ export interface IAttributionCollectionSpec<T> {
}>;
}

// @alpha @deprecated
export interface IClientEvents {
// (undocumented)
(event: "normalize", listener: (target: IEventThisPlaceHolder) => void): void;
// (undocumented)
(event: "delta", listener: (opArgs: IMergeTreeDeltaOpArgs, deltaArgs: IMergeTreeDeltaCallbackArgs, target: IEventThisPlaceHolder) => void): void;
// (undocumented)
(event: "maintenance", listener: (args: IMergeTreeMaintenanceCallbackArgs, deltaArgs: IMergeTreeDeltaOpArgs | undefined, target: IEventThisPlaceHolder) => void): void;
}

// @alpha (undocumented)
export interface IJSONMarkerSegment extends IJSONSegment {
// (undocumented)
Expand Down Expand Up @@ -302,12 +185,6 @@ export interface IMergeTreeAnnotateMsg extends IMergeTreeDelta {
type: typeof MergeTreeDeltaType.ANNOTATE;
}

// @alpha @deprecated (undocumented)
export interface IMergeTreeAttributionOptions {
policyFactory?: () => AttributionPolicy;
track?: boolean;
}

// @alpha (undocumented)
export interface IMergeTreeDelta {
type: MergeTreeDeltaType;
Expand Down Expand Up @@ -392,7 +269,6 @@ export type IMergeTreeOp = IMergeTreeDeltaOp | IMergeTreeGroupMsg;

// @alpha (undocumented)
export interface IMergeTreeOptions {
attribution?: IMergeTreeAttributionOptions;
// (undocumented)
catchUpBlobName?: string;
mergeTreeEnableObliterate?: boolean;
Expand Down
21 changes: 13 additions & 8 deletions packages/dds/merge-tree/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ import { MergeTreeTextHelper } from "./MergeTreeTextHelper.js";
import { DoublyLinkedList, RedBlackTree } from "./collections/index.js";
import { UnassignedSequenceNumber, UniversalSequenceNumber } from "./constants.js";
import { LocalReferencePosition, SlidingPreference } from "./localReference.js";
import { IMergeTreeOptions, MergeTree, errorIfOptionNotTrue } from "./mergeTree.js";
import {
MergeTree,
errorIfOptionNotTrue,
type IMergeTreeOptionsInternal,
} from "./mergeTree.js";
import type {
IMergeTreeClientSequenceArgs,
IMergeTreeDeltaCallbackArgs,
Expand Down Expand Up @@ -100,9 +104,7 @@ export interface IIntegerRange {
* Emitted before this client's merge-tree normalizes its segments on reconnect, potentially
* ordering them. Useful for DDS-like consumers built atop the merge-tree to compute any information
* they need for rebasing their ops on reconnection.
* @legacy
* @alpha
* @deprecated This functionality was not meant to be exported and will be removed in a future release
* @internal
*/
export interface IClientEvents {
(event: "normalize", listener: (target: IEventThisPlaceHolder) => void): void;
Expand All @@ -125,9 +127,12 @@ export interface IClientEvents {
}

/**
* @deprecated This functionality was not meant to be exported and will be removed in a future release
* @legacy
* @alpha
* This class encapsulates a merge-tree, and provides a local client specific view over it and
* the capability to modify it as the local client. Additionally it provides
* binding for processing remote ops on the encapsulated merge tree, and projects local and remote events
* caused by all modification to the underlying merge-tree.
*
* @internal
*/
export class Client extends TypedEventEmitter<IClientEvents> {
public longClientId: string | undefined;
Expand Down Expand Up @@ -155,7 +160,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
constructor(
public readonly specToSegment: (spec: IJSONSegment) => ISegment,
public readonly logger: ITelemetryLoggerExt,
options?: IMergeTreeOptions & PropertySet,
options?: IMergeTreeOptionsInternal & PropertySet,
private readonly getMinInFlightRefSeq: () => number | undefined = (): undefined =>
undefined,
) {
Expand Down
1 change: 1 addition & 0 deletions packages/dds/merge-tree/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export {
AttributionPolicy,
IMergeTreeAttributionOptions,
IMergeTreeOptions,
IMergeTreeOptionsInternal,
getSlideToSegoff,
} from "./mergeTree.js";
export {
Expand Down
28 changes: 14 additions & 14 deletions packages/dds/merge-tree/src/mergeTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { assert, Heap, IComparer } from "@fluidframework/core-utils/internal";
import { DataProcessingError, UsageError } from "@fluidframework/telemetry-utils/internal";

import { IAttributionCollectionSerializer } from "./attributionCollection.js";
// eslint-disable-next-line import/no-deprecated
import { Client } from "./client.js";
import { DoublyLinkedList, ListNode } from "./collections/index.js";
import {
Expand Down Expand Up @@ -177,11 +176,6 @@ export interface IMergeTreeOptions {
*/
newMergeTreeSnapshotFormat?: boolean;

/**
* Options related to attribution
*/
attribution?: IMergeTreeAttributionOptions;

/**
* Enables support for the obliterate operation -- a stronger form of remove
* which deletes concurrently inserted segments
Expand Down Expand Up @@ -212,6 +206,17 @@ export interface IMergeTreeOptions {
*/
mergeTreeEnableSidedObliterate?: boolean;
}

/**
* @internal
*/
export interface IMergeTreeOptionsInternal extends IMergeTreeOptions {
/**
* Options related to attribution
*/
attribution?: IMergeTreeAttributionOptions;
}

export function errorIfOptionNotTrue(
options: IMergeTreeOptions | undefined,
option: keyof IMergeTreeOptions,
Expand All @@ -222,9 +227,7 @@ export function errorIfOptionNotTrue(
}

/**
* @legacy
* @alpha
* @deprecated This functionality was not meant to be exported and will be removed in a future release
* @internal
*/
export interface IMergeTreeAttributionOptions {
/**
Expand All @@ -250,9 +253,7 @@ export interface IMergeTreeAttributionOptions {
/**
* Implements policy dictating which kinds of operations should be attributed and how.
* @sealed
* @legacy
* @alpha
* @deprecated This functionality was not meant to be exported and will be removed in a future release
* @internal
*/
export interface AttributionPolicy {
/**
Expand All @@ -262,7 +263,6 @@ export interface AttributionPolicy {
*
* This must be done in an eventually consistent fashion.
*/
// eslint-disable-next-line import/no-deprecated
attach: (client: Client) => void;
/**
* Disables tracking attribution information on segments.
Expand Down Expand Up @@ -527,7 +527,7 @@ export class MergeTree {

private readonly obliterates = new Obliterates(this);

public constructor(public options?: IMergeTreeOptions) {
public constructor(public options?: IMergeTreeOptionsInternal) {
this._root = this.makeBlock(0);
this._root.mergeTree = this;
this.attributionPolicy = options?.attribution?.policyFactory?.();
Expand Down
10 changes: 7 additions & 3 deletions packages/dds/merge-tree/src/mergeTreeNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export interface ISegment extends IMergeNodeCommon, Partial<IRemovalInfo>, Parti
* This is defined if and only if the insertion of the segment is pending ack, i.e. `seq` is UnassignedSequenceNumber.
* Once the segment is acked, this field is cleared.
*
* @privateRemarks
* See {@link CollaborationWindow.localSeq} for more information on the semantics of localSeq.
*/
localSeq?: number;
Expand All @@ -274,6 +275,8 @@ export interface ISegment extends IMergeNodeCommon, Partial<IRemovalInfo>, Parti
* will be updated to the seq at which that client removed this segment.
*
* Like {@link ISegment.localSeq}, this field is cleared once the local removal of the segment is acked.
*
* @privateRemarks
* See {@link CollaborationWindow.localSeq} for more information on the semantics of localSeq.
*/
localRemovedSeq?: number;
Expand Down Expand Up @@ -896,9 +899,10 @@ export class Marker extends BaseSegment implements ReferencePosition, ISegment {
}

/**
* @deprecated This functionality was not meant to be exported and will be removed in a future release
* @legacy
* @alpha
* This class is used to track facts about the current window of collaboration. This window is defined by the server
* specified minimum sequence number to the last sequence number seen. Additionally, it track state for outstanding
* local operations.
* @internal
*/
export class CollaborationWindow {
clientId = LocalClientId;
Expand Down
7 changes: 6 additions & 1 deletion packages/dds/merge-tree/src/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ export {
runMergeTreeOperationRunner,
TestOperation,
} from "./mergeTreeOperationRunner.js";
export { LRUSegment, MergeTree } from "../mergeTree.js";
export {
LRUSegment,
MergeTree,
IMergeTreeOptions,
IMergeTreeOptionsInternal,
} from "../mergeTree.js";
export { MergeTreeTextHelper } from "../MergeTreeTextHelper.js";
export { SnapshotLegacy } from "../snapshotlegacy.js";
export {
Expand Down
4 changes: 2 additions & 2 deletions packages/dds/merge-tree/src/test/snapshot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import {
createInsertOnlyAttributionPolicy,
createPropertyTrackingAttributionPolicyFactory,
} from "../attributionPolicy.js";
import { IMergeTreeOptions } from "../mergeTree.js";
import { IMergeTreeOptionsInternal } from "../mergeTree.js";
import { SnapshotV1 } from "../snapshotV1.js";

import { TestString, loadSnapshot } from "./snapshot.utils.js";

function makeSnapshotSuite(options?: IMergeTreeOptions): void {
function makeSnapshotSuite(options?: IMergeTreeOptionsInternal): void {
describe("from an empty initial state", () => {
let str: TestString;
beforeEach(() => {
Expand Down
Loading

0 comments on commit 2aa0b5e

Please sign in to comment.