From de226b24d9f017d58b23c65b14da475974e78326 Mon Sep 17 00:00:00 2001 From: Tony Murphy Date: Thu, 4 Feb 2021 16:36:42 -0800 Subject: [PATCH] Add Event to MergeTree and Sequence on Local Segment Op Ack (#5045) (#5054) Emit a new maintenance event, ACKNOWLEDGED when the op is round tripped from the server and the local segment is ack --- packages/dds/merge-tree/src/mergeTree.ts | 23 ++++++++++++++++--- .../merge-tree/src/mergeTreeDeltaCallback.ts | 7 +++++- ...ree.markRangeRemoved.deltaCallback.spec.ts | 1 + packages/dds/sequence/src/sequence.ts | 4 ++-- .../dds/sequence/src/sequenceDeltaEvent.ts | 1 + 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/dds/merge-tree/src/mergeTree.ts b/packages/dds/merge-tree/src/mergeTree.ts index 92ecc5cc53d3..5078c920b792 100644 --- a/packages/dds/merge-tree/src/mergeTree.ts +++ b/packages/dds/merge-tree/src/mergeTree.ts @@ -1300,7 +1300,8 @@ export class MergeTree { this.mergeTreeMaintenanceCallback({ operation: MergeTreeMaintenanceType.UNLINK, deltaSegments: [{ segment }], - }); + }, + undefined); } segment.parent = undefined; @@ -1325,7 +1326,8 @@ export class MergeTree { this.mergeTreeMaintenanceCallback({ operation: MergeTreeMaintenanceType.APPEND, deltaSegments: [{ segment: prevSegment! }, { segment }], - }); + }, + undefined); } segment.parent = undefined; segment.trackingCollection.trackingGroups.forEach((tg) => tg.unlink(segment)); @@ -1881,6 +1883,8 @@ export class MergeTree { if (verboseOps) { console.log(`segment group has ${pendingSegmentGroup.segments.length} segments`); } + + const deltaSegments: IMergeTreeSegmentDelta[] = []; pendingSegmentGroup.segments.map((pendingSegment) => { overwrite = !pendingSegment.ack(pendingSegmentGroup, opArgs, this) || overwrite; if (MergeTree.options.zamboniSegments) { @@ -1889,7 +1893,19 @@ export class MergeTree { if (!nodesToUpdate.includes(pendingSegment.parent!)) { nodesToUpdate.push(pendingSegment.parent!); } + deltaSegments.push({ + segment:pendingSegment, + }); }); + if(this.mergeTreeMaintenanceCallback) { + this.mergeTreeMaintenanceCallback( + { + deltaSegments, + operation: MergeTreeMaintenanceType.ACKNOWLEDGED, + }, + opArgs, + ); + } const clientId = this.collabWindow.clientId; for (const node of nodesToUpdate) { this.blockUpdatePathLengths(node, seq, clientId, overwrite); @@ -2227,7 +2243,8 @@ export class MergeTree { this.mergeTreeMaintenanceCallback({ operation: MergeTreeMaintenanceType.SPLIT, deltaSegments: [{ segment }, { segment: next }], - }); + }, + undefined); } return { next }; diff --git a/packages/dds/merge-tree/src/mergeTreeDeltaCallback.ts b/packages/dds/merge-tree/src/mergeTreeDeltaCallback.ts index 308fe9c44acf..c2e954a9bf85 100644 --- a/packages/dds/merge-tree/src/mergeTreeDeltaCallback.ts +++ b/packages/dds/merge-tree/src/mergeTreeDeltaCallback.ts @@ -25,6 +25,11 @@ export const enum MergeTreeMaintenanceType { * b) The segment's tracking collection is empty (e.g., not being tracked for undo/redo). */ UNLINK = -3, + /** + * Notification that a local change has been acknowledged by the server. + * This means that it has made the round trip to the server and has had a sequence number assigned. + */ + ACKNOWLEDGED = -4, } export type MergeTreeDeltaOperationTypes = MergeTreeDeltaOperationType | MergeTreeMaintenanceType; @@ -70,4 +75,4 @@ export type MergeTreeDeltaCallback = export interface IMergeTreeMaintenanceCallbackArgs extends IMergeTreeDeltaCallbackArgs { } export type MergeTreeMaintenanceCallback = - (MaintenanceArgs: IMergeTreeMaintenanceCallbackArgs) => void; + (MaintenanceArgs: IMergeTreeMaintenanceCallbackArgs, opArgs: IMergeTreeDeltaOpArgs | undefined) => void; diff --git a/packages/dds/merge-tree/src/test/mergeTree.markRangeRemoved.deltaCallback.spec.ts b/packages/dds/merge-tree/src/test/mergeTree.markRangeRemoved.deltaCallback.spec.ts index ff131d7f3fe2..0488d47aa308 100644 --- a/packages/dds/merge-tree/src/test/mergeTree.markRangeRemoved.deltaCallback.spec.ts +++ b/packages/dds/merge-tree/src/test/mergeTree.markRangeRemoved.deltaCallback.spec.ts @@ -88,6 +88,7 @@ describe("MergeTree", () => { [MergeTreeDeltaType.REMOVE]: 1, [MergeTreeMaintenanceType.SPLIT]: 2, [MergeTreeMaintenanceType.UNLINK]: 1, + [MergeTreeMaintenanceType.ACKNOWLEDGED]: 1, }); }); diff --git a/packages/dds/sequence/src/sequence.ts b/packages/dds/sequence/src/sequence.ts index 4c66c4200a9a..6ebc17158276 100644 --- a/packages/dds/sequence/src/sequence.ts +++ b/packages/dds/sequence/src/sequence.ts @@ -144,8 +144,8 @@ export abstract class SharedSegmentSequence break; case "maintenance": if (!this.client.mergeTreeMaintenanceCallback) { - this.client.mergeTreeMaintenanceCallback = (args) => { - this.emit("maintenance", new SequenceMaintenanceEvent(args, this.client), this); + this.client.mergeTreeMaintenanceCallback = (args, opArgs) => { + this.emit("maintenance", new SequenceMaintenanceEvent(opArgs, args, this.client), this); }; } break; diff --git a/packages/dds/sequence/src/sequenceDeltaEvent.ts b/packages/dds/sequence/src/sequenceDeltaEvent.ts index cccd8aaff345..8a5afee82ebe 100644 --- a/packages/dds/sequence/src/sequenceDeltaEvent.ts +++ b/packages/dds/sequence/src/sequenceDeltaEvent.ts @@ -126,6 +126,7 @@ export class SequenceDeltaEvent extends SequenceEvent { constructor( + public readonly opArgs: IMergeTreeDeltaOpArgs | undefined, deltaArgs: IMergeTreeMaintenanceCallbackArgs, mergeTreeClient: Client, ) {