@fluidframework/merge-tree 2.31.0 → 2.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/client.d.ts +7 -1
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +153 -44
  5. package/dist/client.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/mergeTree.d.ts +17 -5
  11. package/dist/mergeTree.d.ts.map +1 -1
  12. package/dist/mergeTree.js +188 -79
  13. package/dist/mergeTree.js.map +1 -1
  14. package/dist/mergeTreeNodes.d.ts +16 -18
  15. package/dist/mergeTreeNodes.d.ts.map +1 -1
  16. package/dist/mergeTreeNodes.js +6 -0
  17. package/dist/mergeTreeNodes.js.map +1 -1
  18. package/dist/perspective.d.ts +9 -0
  19. package/dist/perspective.d.ts.map +1 -1
  20. package/dist/perspective.js +14 -1
  21. package/dist/perspective.js.map +1 -1
  22. package/dist/segmentInfos.d.ts +32 -4
  23. package/dist/segmentInfos.d.ts.map +1 -1
  24. package/dist/segmentInfos.js +3 -1
  25. package/dist/segmentInfos.js.map +1 -1
  26. package/dist/sortedSegmentSet.d.ts +1 -0
  27. package/dist/sortedSegmentSet.d.ts.map +1 -1
  28. package/dist/sortedSegmentSet.js +3 -0
  29. package/dist/sortedSegmentSet.js.map +1 -1
  30. package/dist/test/beastTest.spec.js +5 -5
  31. package/dist/test/beastTest.spec.js.map +1 -1
  32. package/dist/test/client.localReference.spec.js +3 -3
  33. package/dist/test/client.localReference.spec.js.map +1 -1
  34. package/dist/test/client.rollback.spec.js +17 -0
  35. package/dist/test/client.rollback.spec.js.map +1 -1
  36. package/dist/test/clientTestHelper.d.ts +100 -0
  37. package/dist/test/clientTestHelper.d.ts.map +1 -0
  38. package/dist/test/clientTestHelper.js +196 -0
  39. package/dist/test/clientTestHelper.js.map +1 -0
  40. package/dist/test/mergeTree.annotate.spec.js +12 -12
  41. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  42. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
  43. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  44. package/dist/test/obliterate.concurrent.spec.js +93 -90
  45. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  46. package/dist/test/obliterate.deltaCallback.spec.js +121 -116
  47. package/dist/test/obliterate.deltaCallback.spec.js.map +1 -1
  48. package/dist/test/obliterate.rangeExpansion.spec.js +29 -79
  49. package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
  50. package/dist/test/obliterate.reconnect.spec.js +235 -58
  51. package/dist/test/obliterate.reconnect.spec.js.map +1 -1
  52. package/dist/test/testClient.js +1 -1
  53. package/dist/test/testClient.js.map +1 -1
  54. package/dist/test/testUtils.d.ts +13 -0
  55. package/dist/test/testUtils.d.ts.map +1 -1
  56. package/dist/test/testUtils.js +22 -1
  57. package/dist/test/testUtils.js.map +1 -1
  58. package/lib/client.d.ts +7 -1
  59. package/lib/client.d.ts.map +1 -1
  60. package/lib/client.js +155 -46
  61. package/lib/client.js.map +1 -1
  62. package/lib/index.d.ts +1 -1
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js +1 -0
  65. package/lib/index.js.map +1 -1
  66. package/lib/mergeTree.d.ts +17 -5
  67. package/lib/mergeTree.d.ts.map +1 -1
  68. package/lib/mergeTree.js +192 -83
  69. package/lib/mergeTree.js.map +1 -1
  70. package/lib/mergeTreeNodes.d.ts +16 -18
  71. package/lib/mergeTreeNodes.d.ts.map +1 -1
  72. package/lib/mergeTreeNodes.js +7 -1
  73. package/lib/mergeTreeNodes.js.map +1 -1
  74. package/lib/perspective.d.ts +9 -0
  75. package/lib/perspective.d.ts.map +1 -1
  76. package/lib/perspective.js +12 -0
  77. package/lib/perspective.js.map +1 -1
  78. package/lib/segmentInfos.d.ts +32 -4
  79. package/lib/segmentInfos.d.ts.map +1 -1
  80. package/lib/segmentInfos.js +2 -1
  81. package/lib/segmentInfos.js.map +1 -1
  82. package/lib/sortedSegmentSet.d.ts +1 -0
  83. package/lib/sortedSegmentSet.d.ts.map +1 -1
  84. package/lib/sortedSegmentSet.js +3 -0
  85. package/lib/sortedSegmentSet.js.map +1 -1
  86. package/lib/test/beastTest.spec.js +5 -5
  87. package/lib/test/beastTest.spec.js.map +1 -1
  88. package/lib/test/client.localReference.spec.js +3 -3
  89. package/lib/test/client.localReference.spec.js.map +1 -1
  90. package/lib/test/client.rollback.spec.js +18 -1
  91. package/lib/test/client.rollback.spec.js.map +1 -1
  92. package/lib/test/clientTestHelper.d.ts +100 -0
  93. package/lib/test/clientTestHelper.d.ts.map +1 -0
  94. package/lib/test/clientTestHelper.js +192 -0
  95. package/lib/test/clientTestHelper.js.map +1 -0
  96. package/lib/test/mergeTree.annotate.spec.js +12 -12
  97. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  98. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
  99. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  100. package/lib/test/obliterate.concurrent.spec.js +93 -90
  101. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  102. package/lib/test/obliterate.deltaCallback.spec.js +121 -116
  103. package/lib/test/obliterate.deltaCallback.spec.js.map +1 -1
  104. package/lib/test/obliterate.rangeExpansion.spec.js +1 -51
  105. package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
  106. package/lib/test/obliterate.reconnect.spec.js +236 -59
  107. package/lib/test/obliterate.reconnect.spec.js.map +1 -1
  108. package/lib/test/testClient.js +1 -1
  109. package/lib/test/testClient.js.map +1 -1
  110. package/lib/test/testUtils.d.ts +13 -0
  111. package/lib/test/testUtils.d.ts.map +1 -1
  112. package/lib/test/testUtils.js +20 -0
  113. package/lib/test/testUtils.js.map +1 -1
  114. package/package.json +19 -18
  115. package/src/client.ts +286 -55
  116. package/src/index.ts +1 -1
  117. package/src/mergeTree.ts +265 -98
  118. package/src/mergeTreeNodes.ts +24 -18
  119. package/src/perspective.ts +21 -0
  120. package/src/segmentInfos.ts +48 -6
  121. package/src/sortedSegmentSet.ts +4 -0
  122. package/dist/test/partialSyncHelper.d.ts +0 -42
  123. package/dist/test/partialSyncHelper.d.ts.map +0 -1
  124. package/dist/test/partialSyncHelper.js +0 -96
  125. package/dist/test/partialSyncHelper.js.map +0 -1
  126. package/dist/test/reconnectHelper.d.ts +0 -50
  127. package/dist/test/reconnectHelper.d.ts.map +0 -1
  128. package/dist/test/reconnectHelper.js +0 -106
  129. package/dist/test/reconnectHelper.js.map +0 -1
  130. package/lib/test/partialSyncHelper.d.ts +0 -42
  131. package/lib/test/partialSyncHelper.d.ts.map +0 -1
  132. package/lib/test/partialSyncHelper.js +0 -92
  133. package/lib/test/partialSyncHelper.js.map +0 -1
  134. package/lib/test/reconnectHelper.d.ts +0 -50
  135. package/lib/test/reconnectHelper.d.ts.map +0 -1
  136. package/lib/test/reconnectHelper.js +0 -102
  137. package/lib/test/reconnectHelper.js.map +0 -1
@@ -14,7 +14,7 @@ import {
14
14
  UniversalSequenceNumber,
15
15
  } from "./constants.js";
16
16
  import { LocalReferenceCollection, type LocalReferencePosition } from "./localReference.js";
17
- import { TrackingGroupCollection } from "./mergeTreeTracking.js";
17
+ import { TrackingGroupCollection, type ITrackingGroup } from "./mergeTreeTracking.js";
18
18
  import { IJSONSegment, IMarkerDef, ReferenceType } from "./ops.js";
19
19
  import { computeHierarchicalOrdinal } from "./ordinal.js";
20
20
  import type { PartialSequenceLengths } from "./partialLengths.js";
@@ -32,8 +32,11 @@ import {
32
32
  type IMergeNodeInfo,
33
33
  type IHasRemovalInfo,
34
34
  type SegmentWithInfo,
35
+ ISegmentInsideObliterateInfo,
36
+ isInsideObliterate,
35
37
  } from "./segmentInfos.js";
36
38
  import { PropertiesManager } from "./segmentPropertiesManager.js";
39
+ import type { Side } from "./sequencePlace.js";
37
40
  import type { OperationStamp, SliceRemoveOperationStamp } from "./stamps.js";
38
41
 
39
42
  /**
@@ -77,23 +80,6 @@ export interface ISegmentInternal extends ISegment {
77
80
  export interface ISegmentPrivate extends ISegmentInternal {
78
81
  segmentGroups?: SegmentGroupCollection;
79
82
  propertyManager?: PropertiesManager;
80
- /**
81
- * Populated iff this segment was inserted into a range affected by concurrent obliterates at the time of its insertion.
82
- * Contains information about the 'most recent' (i.e. 'winning' in the sense below) obliterate.
83
- *
84
- * BEWARE: We have opted for a certain form of last-write wins (LWW) semantics for obliterates:
85
- * the client which last obliterated a range is considered to have "won ownership" of that range and may insert into it
86
- * without that insertion being obliterated by other clients' concurrent obliterates.
87
- *
88
- * Therefore, this field can be populated even if the segment has not been obliterated (i.e. is still visible).
89
- * This happens precisely when the segment was inserted by the same client that 'won' the obliterate (in a scenario where
90
- * a client first issues a sided obliterate impacting a range, then inserts into that range before the server has acked the obliterate).
91
- *
92
- * See the test case "obliterate with mismatched final states" for an example of such a scenario.
93
- *
94
- * TODO:AB#29553: This property is not persisted in the summary, but it should be.
95
- */
96
- obliteratePrecedingInsertion?: ObliterateInfo;
97
83
  }
98
84
  /**
99
85
  * Segment leafs are segments that have both IMergeNodeInfo and IHasInsertionInfo. This means they
@@ -228,10 +214,24 @@ export interface InsertContext {
228
214
 
229
215
  export interface ObliterateInfo {
230
216
  start: LocalReferencePosition;
217
+ startSide: Side;
231
218
  end: LocalReferencePosition;
219
+ endSide: Side;
232
220
  refSeq: number;
233
221
  stamp: SliceRemoveOperationStamp;
234
222
  segmentGroup: SegmentGroup | undefined;
223
+ /**
224
+ * Defined only for unacked obliterates.
225
+ *
226
+ * Contains all segments inserted into the range this obliterate affects where at the time of insertion,
227
+ * this obliterate was the newest concurrent obliterate that overlapped the insertion point (this information
228
+ * is relevant for the tiebreak policy of allowing last-obliterater to insert).
229
+ *
230
+ * We need to keep this around for unacked ops because on reconnect, outstanding local obliterates may have set `obliteratePrecedingInsertion`
231
+ * (tiebreak) on segments they no longer apply to, since the reissued obliterate may affect a smaller range than the original one when content
232
+ * near the obliterate's endpoints was removed by another client between the time of the original obliterate and reissuing.
233
+ */
234
+ tiebreakTrackingGroup: ITrackingGroup | undefined;
235
235
  }
236
236
 
237
237
  export interface SegmentGroup {
@@ -423,6 +423,12 @@ export abstract class BaseSegment implements ISegment {
423
423
  removes: [...this.removes],
424
424
  });
425
425
  }
426
+ if (isInsideObliterate(this)) {
427
+ overwriteInfo<ISegmentInsideObliterateInfo>(leafSegment, {
428
+ obliteratePrecedingInsertion: this.obliteratePrecedingInsertion,
429
+ insertionRefSeqStamp: this.insertionRefSeqStamp,
430
+ });
431
+ }
426
432
 
427
433
  this.trackingCollection.copyTo(leafSegment);
428
434
  if (this.attribution) {
@@ -3,6 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ import { NonCollabClient } from "./constants.js";
6
7
  import { seqLTE, type ISegment } from "./mergeTreeNodes.js";
7
8
  import { isInserted, isRemoved } from "./segmentInfos.js";
8
9
  import * as opstampUtils from "./stamps.js";
@@ -116,6 +117,21 @@ export class LocalReconnectingPerspective extends PerspectiveBase implements Per
116
117
  }
117
118
  }
118
119
 
120
+ /**
121
+ * A perspective which includes edits which were either:
122
+ * - acked and at or before some reference sequence number
123
+ * - unacked, but at or before some local sequence number
124
+ *
125
+ * @internal
126
+ */
127
+ export function createLocalReconnectingPerspective(
128
+ refSeq: number,
129
+ clientId: number,
130
+ localSeq: number,
131
+ ): Perspective {
132
+ return new LocalReconnectingPerspective(refSeq, clientId, localSeq);
133
+ }
134
+
119
135
  /**
120
136
  * A perspective which includes all known edits.
121
137
  *
@@ -169,3 +185,8 @@ function isRemoveOperationStamp(stamp: OperationStamp): stamp is RemoveOperation
169
185
  const { type } = stamp as unknown as RemoveOperationStamp;
170
186
  return type === "setRemove" || type === "sliceRemove";
171
187
  }
188
+
189
+ export const allAckedChangesPerspective = new PriorPerspective(
190
+ Number.MAX_SAFE_INTEGER,
191
+ NonCollabClient,
192
+ );
@@ -6,8 +6,13 @@
6
6
  import { assert, isObject } from "@fluidframework/core-utils/internal";
7
7
 
8
8
  import { UnassignedSequenceNumber } from "./constants.js";
9
- import { ISegmentInternal, ISegmentPrivate, MergeBlock } from "./mergeTreeNodes.js";
10
- import type { InsertOperationStamp, RemoveOperationStamp } from "./stamps.js";
9
+ import {
10
+ ISegmentInternal,
11
+ ISegmentPrivate,
12
+ MergeBlock,
13
+ type ObliterateInfo,
14
+ } from "./mergeTreeNodes.js";
15
+ import type { InsertOperationStamp, OperationStamp, RemoveOperationStamp } from "./stamps.js";
11
16
 
12
17
  export interface StringToType {
13
18
  "string": string;
@@ -50,6 +55,34 @@ export interface IHasInsertionInfo {
50
55
  insert: InsertOperationStamp;
51
56
  }
52
57
 
58
+ export interface ISegmentInsideObliterateInfo {
59
+ /**
60
+ * Populated iff this segment was inserted into a range affected by concurrent obliterates at the time of its insertion.
61
+ * Contains information about the 'most recent' (i.e. 'winning' in the sense below) obliterate.
62
+ *
63
+ * BEWARE: We have opted for a certain form of last-write wins (LWW) semantics for obliterates:
64
+ * the client which last obliterated a range is considered to have "won ownership" of that range and may insert into it
65
+ * without that insertion being obliterated by other clients' concurrent obliterates.
66
+ *
67
+ * Therefore, this field can be populated even if the segment has not been obliterated (i.e. is still visible).
68
+ * This happens precisely when the segment was inserted by the same client that 'won' the obliterate (in a scenario where
69
+ * a client first issues a sided obliterate impacting a range, then inserts into that range before the server has acked the obliterate).
70
+ *
71
+ * See the test case "obliterate with mismatched final states" for an example of such a scenario.
72
+ *
73
+ * TODO:AB#29553: This property is not persisted in the V1 summary, but it should be.
74
+ */
75
+ obliteratePrecedingInsertion?: ObliterateInfo;
76
+ /**
77
+ * Populated iff this segment was inserted into a range concurrently removed by a local obliterate operation.
78
+ * This field is unset once the newest such overlapping obliterate is acked, and allows recomputing {@link obliteratePrecedingInsertion}
79
+ * if that local obliterate is resubmitted.
80
+ *
81
+ * TODO:AB#29553: This property is not persisted in the V1 summary, but it should be.
82
+ */
83
+ insertionRefSeqStamp?: OperationStamp;
84
+ }
85
+
53
86
  /**
54
87
  * Converts a segment-like object to an insertion info object if possible.
55
88
  *
@@ -75,6 +108,11 @@ export const toInsertionInfo = (segmentLike: unknown): IHasInsertionInfo | undef
75
108
  export const isInserted = (segmentLike: unknown): segmentLike is IHasInsertionInfo =>
76
109
  toInsertionInfo(segmentLike) !== undefined;
77
110
 
111
+ export const isInsideObliterate = (
112
+ segmentLike: unknown,
113
+ ): segmentLike is ISegmentInsideObliterateInfo =>
114
+ segmentLike !== undefined && hasProp(segmentLike, "obliteratePrecedingInsertion", "object");
115
+
78
116
  /**
79
117
  * Asserts that the segment has insertion info. Usage of this function should not produce a user facing error.
80
118
  *
@@ -227,9 +265,9 @@ export const assertRemoved: <T extends Partial<IHasRemovalInfo> | undefined>(
227
265
  * ensures no further usage of the removed removal info is allowed. if continued use is required other
228
266
  * type coercion methods should be use to correctly re-type the variable.
229
267
  */
230
- export const removeRemovalInfo: (nodeLike: IHasRemovalInfo) => asserts nodeLike is never = (
231
- nodeLike,
232
- ) =>
268
+ export const removeRemovalInfo: (
269
+ nodeLike: IHasRemovalInfo,
270
+ ) => asserts nodeLike is Record<keyof IHasRemovalInfo, never> = (nodeLike) =>
233
271
  Object.assign<IHasRemovalInfo, Record<keyof IHasRemovalInfo, undefined>>(nodeLike, {
234
272
  removes: undefined,
235
273
  });
@@ -257,7 +295,11 @@ export function wasRemovedOnInsert(segment: IHasInsertionInfo & ISegmentPrivate)
257
295
  /**
258
296
  * A union type representing any segment info.
259
297
  */
260
- export type SegmentInfo = IMergeNodeInfo | IHasInsertionInfo | IHasRemovalInfo;
298
+ export type SegmentInfo =
299
+ | IMergeNodeInfo
300
+ | IHasInsertionInfo
301
+ | IHasRemovalInfo
302
+ | ISegmentInsideObliterateInfo;
261
303
 
262
304
  /**
263
305
  * A type representing a segment with additional info.
@@ -57,6 +57,10 @@ export class SortedSegmentSet<
57
57
  return 0;
58
58
  }
59
59
 
60
+ public onSortOrderChange(): void {
61
+ this.sortedItems.sort((a, b) => this.compare(a, b));
62
+ }
63
+
60
64
  protected compare(a: T, b: T): number {
61
65
  const aOrdinal = this.getOrdinal(a);
62
66
  const bOrdinal = this.getOrdinal(b);
@@ -1,42 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
6
- import type { IMergeTreeOptions, InteriorSequencePlace } from "../index.js";
7
- import type { TestClient } from "./testClient.js";
8
- import { TestClientLogger } from "./testClientLogger.js";
9
- declare const ClientIds: readonly ["A", "B", "C", "D"];
10
- type ClientName = (typeof ClientIds)[number];
11
- /**
12
- * Like `ReconnectHelper`, but:
13
- * - does not support reconnecting clients
14
- * - supports advancing only some clients to a given sequence number (not all clients must be synchronized at the same time).
15
- *
16
- * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq
17
- * in lockstep.
18
- */
19
- export declare class PartialSyncTestHelper {
20
- clients: Record<ClientName, TestClient> & {
21
- all: TestClient[];
22
- };
23
- idxFromName(name: ClientName): number;
24
- logger: TestClientLogger;
25
- ops: ISequencedDocumentMessage[];
26
- clientToLastAppliedSeq: Map<"A" | "C" | "B" | "D", number>;
27
- perClientOps: ISequencedDocumentMessage[][];
28
- private seq;
29
- constructor(options?: IMergeTreeOptions);
30
- private addMessage;
31
- insertText(clientName: ClientName, pos: number, text: string): void;
32
- removeRange(clientName: ClientName, start: number, end: number): void;
33
- obliterateRange(clientName: ClientName, start: number | InteriorSequencePlace, end: number | InteriorSequencePlace): void;
34
- advanceClientToSeq(clientName: ClientName, seq: number): void;
35
- /**
36
- * Sends all known ops to the procieded client ids.
37
- */
38
- advanceClients(...clientNames: ClientName[]): void;
39
- processAllOps(): void;
40
- }
41
- export {};
42
- //# sourceMappingURL=partialSyncHelper.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"partialSyncHelper.d.ts","sourceRoot":"","sources":["../../src/test/partialSyncHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAExF,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,QAAA,MAAM,SAAS,+BAAgC,CAAC;AAChD,KAAK,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7C;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IACjC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG;QAAE,GAAG,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAEhE,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIrC,MAAM,EAAE,gBAAgB,CAAC;IAEzB,GAAG,EAAE,yBAAyB,EAAE,CAAM;IACtC,sBAAsB,qCAAiC;IAEvD,YAAY,EAAE,yBAAyB,EAAE,EAAE,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAa;gBAEL,OAAO,GAAE,iBAAsB;IAgBlD,OAAO,CAAC,UAAU;IAUX,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKnE,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAKrE,eAAe,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,GAAG,qBAAqB,EACrC,GAAG,EAAE,MAAM,GAAG,qBAAqB,GACjC,IAAI;IAWA,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAwBpE;;OAEG;IACI,cAAc,CAAC,GAAG,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAOlD,aAAa,IAAI,IAAI;CAM5B"}
@@ -1,96 +0,0 @@
1
- "use strict";
2
- /*!
3
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
- * Licensed under the MIT License.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.PartialSyncTestHelper = void 0;
8
- const node_assert_1 = require("node:assert");
9
- const testClientLogger_js_1 = require("./testClientLogger.js");
10
- const ClientIds = ["A", "B", "C", "D"];
11
- /**
12
- * Like `ReconnectHelper`, but:
13
- * - does not support reconnecting clients
14
- * - supports advancing only some clients to a given sequence number (not all clients must be synchronized at the same time).
15
- *
16
- * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq
17
- * in lockstep.
18
- */
19
- class PartialSyncTestHelper {
20
- idxFromName(name) {
21
- return (name.codePointAt(0) ?? 0) - ("A".codePointAt(0) ?? 0);
22
- }
23
- constructor(options = {}) {
24
- this.ops = [];
25
- this.clientToLastAppliedSeq = new Map();
26
- this.seq = 0;
27
- this.clients = (0, testClientLogger_js_1.createClientsAtInitialState)({
28
- initialState: "",
29
- options: {
30
- mergeTreeEnableObliterate: true,
31
- mergeTreeEnableSidedObliterate: true,
32
- ...options,
33
- },
34
- }, ...ClientIds);
35
- this.logger = new testClientLogger_js_1.TestClientLogger(this.clients.all);
36
- this.perClientOps = this.clients.all.map(() => []);
37
- }
38
- addMessage(message) {
39
- this.ops.push(message);
40
- // This implementation (specifically, that of applying ops / synchronizing clients) assumes messages
41
- // are pushed sequentially starting with seq 1.
42
- (0, node_assert_1.strict)(message.sequenceNumber === this.ops.length, "Partial sync test helper invariant violated");
43
- }
44
- insertText(clientName, pos, text) {
45
- const client = this.clients[clientName];
46
- this.addMessage(client.makeOpMessage(client.insertTextLocal(pos, text), ++this.seq));
47
- }
48
- removeRange(clientName, start, end) {
49
- const client = this.clients[clientName];
50
- this.addMessage(client.makeOpMessage(client.removeRangeLocal(start, end), ++this.seq));
51
- }
52
- obliterateRange(clientName, start, end) {
53
- const client = this.clients[clientName];
54
- this.addMessage(client.makeOpMessage(
55
- // TODO: remove type assertions when sidedness is enabled
56
- client.obliterateRangeLocal(start, end), ++this.seq));
57
- }
58
- advanceClientToSeq(clientName, seq) {
59
- const client = this.clients[clientName];
60
- const lastApplied = this.clientToLastAppliedSeq.get(clientName);
61
- (0, node_assert_1.strict)(seq > 0, "Can only advance clients to sequence numbers that exist");
62
- (0, node_assert_1.strict)(this.ops.length >= seq, "Cannot attempt to advance clients to sequence numbers that don't yet exist");
63
- let startIndex;
64
- if (lastApplied === undefined) {
65
- startIndex = 0;
66
- }
67
- else {
68
- if (lastApplied >= seq) {
69
- return;
70
- }
71
- startIndex = lastApplied;
72
- }
73
- for (let i = startIndex; i < seq; i++) {
74
- const nextMessage = this.ops[i];
75
- client.applyMsg(nextMessage);
76
- this.clientToLastAppliedSeq.set(clientName, nextMessage.sequenceNumber);
77
- }
78
- }
79
- /**
80
- * Sends all known ops to the procieded client ids.
81
- */
82
- advanceClients(...clientNames) {
83
- const latestSeq = this.ops[this.ops.length - 1].sequenceNumber;
84
- for (const name of clientNames) {
85
- this.advanceClientToSeq(name, latestSeq);
86
- }
87
- }
88
- processAllOps() {
89
- const latestSeq = this.ops[this.ops.length - 1].sequenceNumber;
90
- for (const name of ClientIds) {
91
- this.advanceClientToSeq(name, latestSeq);
92
- }
93
- }
94
- }
95
- exports.PartialSyncTestHelper = PartialSyncTestHelper;
96
- //# sourceMappingURL=partialSyncHelper.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"partialSyncHelper.js","sourceRoot":"","sources":["../../src/test/partialSyncHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { IMergeTreeOptions, InteriorSequencePlace } from \"../index.js\";\n\nimport type { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\nconst ClientIds = [\"A\", \"B\", \"C\", \"D\"] as const;\ntype ClientName = (typeof ClientIds)[number];\n\n/**\n * Like `ReconnectHelper`, but:\n * - does not support reconnecting clients\n * - supports advancing only some clients to a given sequence number (not all clients must be synchronized at the same time).\n *\n * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq\n * in lockstep.\n */\nexport class PartialSyncTestHelper {\n\tclients: Record<ClientName, TestClient> & { all: TestClient[] };\n\n\tidxFromName(name: ClientName): number {\n\t\treturn (name.codePointAt(0) ?? 0) - (\"A\".codePointAt(0) ?? 0);\n\t}\n\n\tlogger: TestClientLogger;\n\n\tops: ISequencedDocumentMessage[] = [];\n\tclientToLastAppliedSeq = new Map<ClientName, number>();\n\n\tperClientOps: ISequencedDocumentMessage[][];\n\n\tprivate seq: number = 0;\n\n\tpublic constructor(options: IMergeTreeOptions = {}) {\n\t\tthis.clients = createClientsAtInitialState(\n\t\t\t{\n\t\t\t\tinitialState: \"\",\n\t\t\t\toptions: {\n\t\t\t\t\tmergeTreeEnableObliterate: true,\n\t\t\t\t\tmergeTreeEnableSidedObliterate: true,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t},\n\t\t\t...ClientIds,\n\t\t);\n\t\tthis.logger = new TestClientLogger(this.clients.all);\n\t\tthis.perClientOps = this.clients.all.map(() => []);\n\t}\n\n\tprivate addMessage(message: ISequencedDocumentMessage): void {\n\t\tthis.ops.push(message);\n\t\t// This implementation (specifically, that of applying ops / synchronizing clients) assumes messages\n\t\t// are pushed sequentially starting with seq 1.\n\t\tassert(\n\t\t\tmessage.sequenceNumber === this.ops.length,\n\t\t\t\"Partial sync test helper invariant violated\",\n\t\t);\n\t}\n\n\tpublic insertText(clientName: ClientName, pos: number, text: string): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client.makeOpMessage(client.insertTextLocal(pos, text), ++this.seq));\n\t}\n\n\tpublic removeRange(clientName: ClientName, start: number, end: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client.makeOpMessage(client.removeRangeLocal(start, end), ++this.seq));\n\t}\n\n\tpublic obliterateRange(\n\t\tclientName: ClientName,\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(\n\t\t\tclient.makeOpMessage(\n\t\t\t\t// TODO: remove type assertions when sidedness is enabled\n\t\t\t\tclient.obliterateRangeLocal(start as number, end as number),\n\t\t\t\t++this.seq,\n\t\t\t),\n\t\t);\n\t}\n\n\tpublic advanceClientToSeq(clientName: ClientName, seq: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst lastApplied = this.clientToLastAppliedSeq.get(clientName);\n\t\tassert(seq > 0, \"Can only advance clients to sequence numbers that exist\");\n\t\tassert(\n\t\t\tthis.ops.length >= seq,\n\t\t\t\"Cannot attempt to advance clients to sequence numbers that don't yet exist\",\n\t\t);\n\t\tlet startIndex: number;\n\t\tif (lastApplied === undefined) {\n\t\t\tstartIndex = 0;\n\t\t} else {\n\t\t\tif (lastApplied >= seq) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstartIndex = lastApplied;\n\t\t}\n\t\tfor (let i = startIndex; i < seq; i++) {\n\t\t\tconst nextMessage = this.ops[i];\n\t\t\tclient.applyMsg(nextMessage);\n\t\t\tthis.clientToLastAppliedSeq.set(clientName, nextMessage.sequenceNumber);\n\t\t}\n\t}\n\n\t/**\n\t * Sends all known ops to the procieded client ids.\n\t */\n\tpublic advanceClients(...clientNames: ClientName[]): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of clientNames) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\tpublic processAllOps(): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of ClientIds) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n}\n"]}
@@ -1,50 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
6
- import { type IMergeTreeOptions, type InteriorSequencePlace, type SequencePlace } from "../index.js";
7
- import type { SegmentGroup } from "../mergeTreeNodes.js";
8
- import { IMergeTreeDeltaOp, type IMergeTreeInsertMsg, type IMergeTreeObliterateMsg, type IMergeTreeObliterateSidedMsg, type IMergeTreeRemoveMsg } from "../ops.js";
9
- import type { TestClient } from "./testClient.js";
10
- import { TestClientLogger } from "./testClientLogger.js";
11
- declare const ClientIds: readonly ["A", "B", "C", "D"];
12
- type ClientName = (typeof ClientIds)[number];
13
- export declare class ReconnectTestHelper {
14
- clients: Record<ClientName, TestClient> & {
15
- all: TestClient[];
16
- };
17
- idxFromName(name: ClientName): number;
18
- logger: TestClientLogger;
19
- ops: ISequencedDocumentMessage[];
20
- perClientOps: ISequencedDocumentMessage[][];
21
- seq: number;
22
- constructor(options?: IMergeTreeOptions);
23
- insertText(clientName: ClientName, pos: number, text: string): void;
24
- removeRange(clientName: ClientName, start: number, end: number): void;
25
- obliterateRange(clientName: ClientName, start: number | InteriorSequencePlace, end: number | InteriorSequencePlace): void;
26
- insertTextLocal(clientName: ClientName, pos: number, text: string): {
27
- op: IMergeTreeInsertMsg;
28
- seg: SegmentGroup;
29
- refSeq: number;
30
- };
31
- removeRangeLocal(clientName: ClientName, start: number, end: number): {
32
- op: IMergeTreeRemoveMsg;
33
- seg: SegmentGroup;
34
- refSeq: number;
35
- };
36
- obliterateRangeLocal(clientName: ClientName, start: SequencePlace, end: SequencePlace): {
37
- op: IMergeTreeObliterateMsg | IMergeTreeObliterateSidedMsg;
38
- seg: SegmentGroup;
39
- refSeq: number;
40
- };
41
- disconnect(clientNames: ClientName[]): void;
42
- processAllOps(): void;
43
- reconnect(clientNames: ClientName[]): void;
44
- submitDisconnectedOp(clientName: ClientName, op: {
45
- op: IMergeTreeDeltaOp;
46
- seg: SegmentGroup | SegmentGroup[];
47
- }): void;
48
- }
49
- export {};
50
- //# sourceMappingURL=reconnectHelper.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconnectHelper.d.ts","sourceRoot":"","sources":["../../src/test/reconnectHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAExF,OAAO,EAEN,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EACN,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,QAAA,MAAM,SAAS,+BAAgC,CAAC;AAChD,KAAK,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7C,qBAAa,mBAAmB;IAC/B,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG;QAAE,GAAG,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAEhE,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIrC,MAAM,EAAE,gBAAgB,CAAC;IAEzB,GAAG,EAAE,yBAAyB,EAAE,CAAM;IACtC,YAAY,EAAE,yBAAyB,EAAE,EAAE,CAAC;IAE5C,GAAG,EAAE,MAAM,CAAK;gBAEG,OAAO,GAAE,iBAAsB;IAgB3C,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKnE,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAKrE,eAAe,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,GAAG,qBAAqB,EACrC,GAAG,EAAE,MAAM,GAAG,qBAAqB,GACjC,IAAI;IAWA,eAAe,CACrB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACV;QACF,EAAE,EAAE,mBAAmB,CAAC;QACxB,GAAG,EAAE,YAAY,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KACf;IASM,gBAAgB,CACtB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACT;QACF,EAAE,EAAE,mBAAmB,CAAC;QACxB,GAAG,EAAE,YAAY,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KACf;IASM,oBAAoB,CAC1B,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,aAAa,GAChB;QACF,EAAE,EAAE,uBAAuB,GAAG,4BAA4B,CAAC;QAC3D,GAAG,EAAE,YAAY,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KACf;IAoBM,UAAU,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAY3C,aAAa,IAAI,IAAI;IAOrB,SAAS,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAS1C,oBAAoB,CAC1B,UAAU,EAAE,UAAU,EACtB,EAAE,EAAE;QAAE,EAAE,EAAE,iBAAiB,CAAC;QAAC,GAAG,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;KAAE,GAC/D,IAAI;CAIP"}
@@ -1,106 +0,0 @@
1
- "use strict";
2
- /*!
3
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
- * Licensed under the MIT License.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ReconnectTestHelper = void 0;
8
- const node_assert_1 = require("node:assert");
9
- const index_js_1 = require("../index.js");
10
- const testClientLogger_js_1 = require("./testClientLogger.js");
11
- const ClientIds = ["A", "B", "C", "D"];
12
- class ReconnectTestHelper {
13
- idxFromName(name) {
14
- return (name.codePointAt(0) ?? 0) - ("A".codePointAt(0) ?? 0);
15
- }
16
- constructor(options = {}) {
17
- this.ops = [];
18
- this.seq = 0;
19
- this.clients = (0, testClientLogger_js_1.createClientsAtInitialState)({
20
- initialState: "",
21
- options: {
22
- mergeTreeEnableObliterate: true,
23
- mergeTreeEnableObliterateReconnect: true,
24
- ...options,
25
- },
26
- }, ...ClientIds);
27
- this.logger = new testClientLogger_js_1.TestClientLogger(this.clients.all);
28
- this.perClientOps = this.clients.all.map(() => []);
29
- }
30
- insertText(clientName, pos, text) {
31
- const client = this.clients[clientName];
32
- this.ops.push(client.makeOpMessage(client.insertTextLocal(pos, text), ++this.seq));
33
- }
34
- removeRange(clientName, start, end) {
35
- const client = this.clients[clientName];
36
- this.ops.push(client.makeOpMessage(client.removeRangeLocal(start, end), ++this.seq));
37
- }
38
- obliterateRange(clientName, start, end) {
39
- const client = this.clients[clientName];
40
- this.ops.push(client.makeOpMessage(
41
- // TODO: remove type assertions when sidedness is enabled
42
- client.obliterateRangeLocal(start, end), ++this.seq));
43
- }
44
- insertTextLocal(clientName, pos, text) {
45
- const client = this.clients[clientName];
46
- const op = client.insertTextLocal(pos, text);
47
- (0, node_assert_1.strict)(op);
48
- const seg = client.peekPendingSegmentGroups();
49
- (0, node_assert_1.strict)(seg);
50
- return { op, seg, refSeq: client.getCollabWindow().currentSeq };
51
- }
52
- removeRangeLocal(clientName, start, end) {
53
- const client = this.clients[clientName];
54
- const op = client.removeRangeLocal(start, end);
55
- (0, node_assert_1.strict)(op);
56
- const seg = client.peekPendingSegmentGroups();
57
- (0, node_assert_1.strict)(seg);
58
- return { op, seg, refSeq: client.getCollabWindow().currentSeq };
59
- }
60
- obliterateRangeLocal(clientName, start, end) {
61
- const client = this.clients[clientName];
62
- let { startPos, endPos } = (0, index_js_1.endpointPosAndSide)(start, end);
63
- (0, node_assert_1.strict)(startPos !== undefined && endPos !== undefined, "start and end positions must be defined");
64
- startPos = startPos === "start" ? 0 : startPos;
65
- endPos = endPos === "end" ? client.getLength() : endPos;
66
- (0, node_assert_1.strict)(startPos !== "end" && endPos !== "start", "start cannot be end and end cannot be start");
67
- const op = client.obliterateRangeLocal(startPos, endPos);
68
- (0, node_assert_1.strict)(op);
69
- const seg = client.peekPendingSegmentGroups();
70
- (0, node_assert_1.strict)(seg);
71
- return { op, seg, refSeq: client.getCollabWindow().currentSeq };
72
- }
73
- disconnect(clientNames) {
74
- const clientIdxs = new Set(clientNames.map((element) => this.idxFromName(element)));
75
- for (const op of this.ops.splice(0))
76
- for (const [i, c] of this.clients.all.entries()) {
77
- if (clientIdxs.has(i)) {
78
- this.perClientOps[i].push(op);
79
- }
80
- else {
81
- c.applyMsg(op);
82
- }
83
- }
84
- }
85
- processAllOps() {
86
- for (const op of this.ops.splice(0))
87
- for (const c of this.clients.all) {
88
- c.applyMsg(op);
89
- }
90
- }
91
- reconnect(clientNames) {
92
- const clientIdxs = new Set(clientNames.map((element) => this.idxFromName(element)));
93
- for (const [i, clientOps] of this.perClientOps.entries()) {
94
- if (clientIdxs.has(i)) {
95
- for (const op of clientOps.splice(0))
96
- this.clients.all[i].applyMsg(op);
97
- }
98
- }
99
- }
100
- submitDisconnectedOp(clientName, op) {
101
- const client = this.clients[clientName];
102
- this.ops.push(client.makeOpMessage(client.regeneratePendingOp(op.op, op.seg), ++this.seq));
103
- }
104
- }
105
- exports.ReconnectTestHelper = ReconnectTestHelper;
106
- //# sourceMappingURL=reconnectHelper.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconnectHelper.js","sourceRoot":"","sources":["../../src/test/reconnectHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tendpointPosAndSide,\n\ttype IMergeTreeOptions,\n\ttype InteriorSequencePlace,\n\ttype SequencePlace,\n} from \"../index.js\";\nimport type { SegmentGroup } from \"../mergeTreeNodes.js\";\nimport {\n\tIMergeTreeDeltaOp,\n\ttype IMergeTreeInsertMsg,\n\ttype IMergeTreeObliterateMsg,\n\ttype IMergeTreeObliterateSidedMsg,\n\ttype IMergeTreeRemoveMsg,\n} from \"../ops.js\";\n\nimport type { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\nconst ClientIds = [\"A\", \"B\", \"C\", \"D\"] as const;\ntype ClientName = (typeof ClientIds)[number];\n\nexport class ReconnectTestHelper {\n\tclients: Record<ClientName, TestClient> & { all: TestClient[] };\n\n\tidxFromName(name: ClientName): number {\n\t\treturn (name.codePointAt(0) ?? 0) - (\"A\".codePointAt(0) ?? 0);\n\t}\n\n\tlogger: TestClientLogger;\n\n\tops: ISequencedDocumentMessage[] = [];\n\tperClientOps: ISequencedDocumentMessage[][];\n\n\tseq: number = 0;\n\n\tpublic constructor(options: IMergeTreeOptions = {}) {\n\t\tthis.clients = createClientsAtInitialState(\n\t\t\t{\n\t\t\t\tinitialState: \"\",\n\t\t\t\toptions: {\n\t\t\t\t\tmergeTreeEnableObliterate: true,\n\t\t\t\t\tmergeTreeEnableObliterateReconnect: true,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t},\n\t\t\t...ClientIds,\n\t\t);\n\t\tthis.logger = new TestClientLogger(this.clients.all);\n\t\tthis.perClientOps = this.clients.all.map(() => []);\n\t}\n\n\tpublic insertText(clientName: ClientName, pos: number, text: string): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.ops.push(client.makeOpMessage(client.insertTextLocal(pos, text), ++this.seq));\n\t}\n\n\tpublic removeRange(clientName: ClientName, start: number, end: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.ops.push(client.makeOpMessage(client.removeRangeLocal(start, end), ++this.seq));\n\t}\n\n\tpublic obliterateRange(\n\t\tclientName: ClientName,\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.ops.push(\n\t\t\tclient.makeOpMessage(\n\t\t\t\t// TODO: remove type assertions when sidedness is enabled\n\t\t\t\tclient.obliterateRangeLocal(start as number, end as number),\n\t\t\t\t++this.seq,\n\t\t\t),\n\t\t);\n\t}\n\n\tpublic insertTextLocal(\n\t\tclientName: ClientName,\n\t\tpos: number,\n\t\ttext: string,\n\t): {\n\t\top: IMergeTreeInsertMsg;\n\t\tseg: SegmentGroup;\n\t\trefSeq: number;\n\t} {\n\t\tconst client = this.clients[clientName];\n\t\tconst op = client.insertTextLocal(pos, text);\n\t\tassert(op);\n\t\tconst seg = client.peekPendingSegmentGroups();\n\t\tassert(seg);\n\t\treturn { op, seg, refSeq: client.getCollabWindow().currentSeq };\n\t}\n\n\tpublic removeRangeLocal(\n\t\tclientName: ClientName,\n\t\tstart: number,\n\t\tend: number,\n\t): {\n\t\top: IMergeTreeRemoveMsg;\n\t\tseg: SegmentGroup;\n\t\trefSeq: number;\n\t} {\n\t\tconst client = this.clients[clientName];\n\t\tconst op = client.removeRangeLocal(start, end);\n\t\tassert(op);\n\t\tconst seg = client.peekPendingSegmentGroups();\n\t\tassert(seg);\n\t\treturn { op, seg, refSeq: client.getCollabWindow().currentSeq };\n\t}\n\n\tpublic obliterateRangeLocal(\n\t\tclientName: ClientName,\n\t\tstart: SequencePlace,\n\t\tend: SequencePlace,\n\t): {\n\t\top: IMergeTreeObliterateMsg | IMergeTreeObliterateSidedMsg;\n\t\tseg: SegmentGroup;\n\t\trefSeq: number;\n\t} {\n\t\tconst client = this.clients[clientName];\n\t\tlet { startPos, endPos } = endpointPosAndSide(start, end);\n\t\tassert(\n\t\t\tstartPos !== undefined && endPos !== undefined,\n\t\t\t\"start and end positions must be defined\",\n\t\t);\n\t\tstartPos = startPos === \"start\" ? 0 : startPos;\n\t\tendPos = endPos === \"end\" ? client.getLength() : endPos;\n\t\tassert(\n\t\t\tstartPos !== \"end\" && endPos !== \"start\",\n\t\t\t\"start cannot be end and end cannot be start\",\n\t\t);\n\t\tconst op = client.obliterateRangeLocal(startPos, endPos);\n\t\tassert(op);\n\t\tconst seg = client.peekPendingSegmentGroups();\n\t\tassert(seg);\n\t\treturn { op, seg, refSeq: client.getCollabWindow().currentSeq };\n\t}\n\n\tpublic disconnect(clientNames: ClientName[]): void {\n\t\tconst clientIdxs = new Set(clientNames.map((element) => this.idxFromName(element)));\n\t\tfor (const op of this.ops.splice(0))\n\t\t\tfor (const [i, c] of this.clients.all.entries()) {\n\t\t\t\tif (clientIdxs.has(i)) {\n\t\t\t\t\tthis.perClientOps[i].push(op);\n\t\t\t\t} else {\n\t\t\t\t\tc.applyMsg(op);\n\t\t\t\t}\n\t\t\t}\n\t}\n\n\tpublic processAllOps(): void {\n\t\tfor (const op of this.ops.splice(0))\n\t\t\tfor (const c of this.clients.all) {\n\t\t\t\tc.applyMsg(op);\n\t\t\t}\n\t}\n\n\tpublic reconnect(clientNames: ClientName[]): void {\n\t\tconst clientIdxs = new Set(clientNames.map((element) => this.idxFromName(element)));\n\t\tfor (const [i, clientOps] of this.perClientOps.entries()) {\n\t\t\tif (clientIdxs.has(i)) {\n\t\t\t\tfor (const op of clientOps.splice(0)) this.clients.all[i].applyMsg(op);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic submitDisconnectedOp(\n\t\tclientName: ClientName,\n\t\top: { op: IMergeTreeDeltaOp; seg: SegmentGroup | SegmentGroup[] },\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.ops.push(client.makeOpMessage(client.regeneratePendingOp(op.op, op.seg), ++this.seq));\n\t}\n}\n"]}
@@ -1,42 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
6
- import type { IMergeTreeOptions, InteriorSequencePlace } from "../index.js";
7
- import type { TestClient } from "./testClient.js";
8
- import { TestClientLogger } from "./testClientLogger.js";
9
- declare const ClientIds: readonly ["A", "B", "C", "D"];
10
- type ClientName = (typeof ClientIds)[number];
11
- /**
12
- * Like `ReconnectHelper`, but:
13
- * - does not support reconnecting clients
14
- * - supports advancing only some clients to a given sequence number (not all clients must be synchronized at the same time).
15
- *
16
- * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq
17
- * in lockstep.
18
- */
19
- export declare class PartialSyncTestHelper {
20
- clients: Record<ClientName, TestClient> & {
21
- all: TestClient[];
22
- };
23
- idxFromName(name: ClientName): number;
24
- logger: TestClientLogger;
25
- ops: ISequencedDocumentMessage[];
26
- clientToLastAppliedSeq: Map<"A" | "C" | "B" | "D", number>;
27
- perClientOps: ISequencedDocumentMessage[][];
28
- private seq;
29
- constructor(options?: IMergeTreeOptions);
30
- private addMessage;
31
- insertText(clientName: ClientName, pos: number, text: string): void;
32
- removeRange(clientName: ClientName, start: number, end: number): void;
33
- obliterateRange(clientName: ClientName, start: number | InteriorSequencePlace, end: number | InteriorSequencePlace): void;
34
- advanceClientToSeq(clientName: ClientName, seq: number): void;
35
- /**
36
- * Sends all known ops to the procieded client ids.
37
- */
38
- advanceClients(...clientNames: ClientName[]): void;
39
- processAllOps(): void;
40
- }
41
- export {};
42
- //# sourceMappingURL=partialSyncHelper.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"partialSyncHelper.d.ts","sourceRoot":"","sources":["../../src/test/partialSyncHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAExF,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,QAAA,MAAM,SAAS,+BAAgC,CAAC;AAChD,KAAK,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7C;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IACjC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG;QAAE,GAAG,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAEhE,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIrC,MAAM,EAAE,gBAAgB,CAAC;IAEzB,GAAG,EAAE,yBAAyB,EAAE,CAAM;IACtC,sBAAsB,qCAAiC;IAEvD,YAAY,EAAE,yBAAyB,EAAE,EAAE,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAa;gBAEL,OAAO,GAAE,iBAAsB;IAgBlD,OAAO,CAAC,UAAU;IAUX,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKnE,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAKrE,eAAe,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,GAAG,qBAAqB,EACrC,GAAG,EAAE,MAAM,GAAG,qBAAqB,GACjC,IAAI;IAWA,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAwBpE;;OAEG;IACI,cAAc,CAAC,GAAG,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAOlD,aAAa,IAAI,IAAI;CAM5B"}