@fluidframework/merge-tree 2.2.0 → 2.3.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 (168) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/api-report/merge-tree.legacy.alpha.api.md +20 -0
  3. package/dist/attributionCollection.d.ts.map +1 -1
  4. package/dist/attributionCollection.js +1 -29
  5. package/dist/attributionCollection.js.map +1 -1
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +3 -4
  8. package/dist/client.js.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/legacy.d.ts +1 -0
  13. package/dist/localReference.d.ts.map +1 -1
  14. package/dist/localReference.js +0 -2
  15. package/dist/localReference.js.map +1 -1
  16. package/dist/mergeTree.d.ts +1 -30
  17. package/dist/mergeTree.d.ts.map +1 -1
  18. package/dist/mergeTree.js +131 -167
  19. package/dist/mergeTree.js.map +1 -1
  20. package/dist/mergeTreeNodes.d.ts +16 -1
  21. package/dist/mergeTreeNodes.d.ts.map +1 -1
  22. package/dist/mergeTreeNodes.js +5 -2
  23. package/dist/mergeTreeNodes.js.map +1 -1
  24. package/dist/partialLengths.d.ts.map +1 -1
  25. package/dist/partialLengths.js +8 -54
  26. package/dist/partialLengths.js.map +1 -1
  27. package/dist/properties.d.ts.map +1 -1
  28. package/dist/properties.js +0 -2
  29. package/dist/properties.js.map +1 -1
  30. package/dist/revertibles.d.ts.map +1 -1
  31. package/dist/revertibles.js +0 -14
  32. package/dist/revertibles.js.map +1 -1
  33. package/dist/segmentGroupCollection.d.ts.map +1 -1
  34. package/dist/segmentGroupCollection.js +0 -2
  35. package/dist/segmentGroupCollection.js.map +1 -1
  36. package/dist/segmentPropertiesManager.d.ts.map +1 -1
  37. package/dist/segmentPropertiesManager.js +1 -3
  38. package/dist/segmentPropertiesManager.js.map +1 -1
  39. package/dist/snapshotLoader.d.ts.map +1 -1
  40. package/dist/snapshotLoader.js +1 -4
  41. package/dist/snapshotLoader.js.map +1 -1
  42. package/dist/snapshotV1.d.ts.map +1 -1
  43. package/dist/snapshotV1.js +1 -11
  44. package/dist/snapshotV1.js.map +1 -1
  45. package/dist/snapshotlegacy.d.ts.map +1 -1
  46. package/dist/snapshotlegacy.js +0 -1
  47. package/dist/snapshotlegacy.js.map +1 -1
  48. package/dist/sortedSegmentSet.d.ts +0 -1
  49. package/dist/sortedSegmentSet.d.ts.map +1 -1
  50. package/dist/sortedSegmentSet.js +1 -9
  51. package/dist/sortedSegmentSet.js.map +1 -1
  52. package/dist/sortedSet.d.ts.map +1 -1
  53. package/dist/sortedSet.js +0 -4
  54. package/dist/sortedSet.js.map +1 -1
  55. package/dist/test/client.conflictFarm.spec.d.ts.map +1 -1
  56. package/dist/test/client.conflictFarm.spec.js +36 -27
  57. package/dist/test/client.conflictFarm.spec.js.map +1 -1
  58. package/dist/test/client.replay.spec.js +1 -1
  59. package/dist/test/client.replay.spec.js.map +1 -1
  60. package/dist/test/mergeTreeOperationRunner.d.ts +2 -1
  61. package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
  62. package/dist/test/mergeTreeOperationRunner.js +29 -11
  63. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  64. package/dist/test/obliterate.spec.js +55 -0
  65. package/dist/test/obliterate.spec.js.map +1 -1
  66. package/dist/test/reconnectHelper.d.ts +0 -1
  67. package/dist/test/reconnectHelper.d.ts.map +1 -1
  68. package/dist/test/reconnectHelper.js +1 -1
  69. package/dist/test/reconnectHelper.js.map +1 -1
  70. package/dist/test/testClientLogger.d.ts.map +1 -1
  71. package/dist/test/testClientLogger.js +17 -7
  72. package/dist/test/testClientLogger.js.map +1 -1
  73. package/dist/zamboni.d.ts.map +1 -1
  74. package/dist/zamboni.js +0 -4
  75. package/dist/zamboni.js.map +1 -1
  76. package/lib/attributionCollection.d.ts.map +1 -1
  77. package/lib/attributionCollection.js +1 -29
  78. package/lib/attributionCollection.js.map +1 -1
  79. package/lib/client.d.ts.map +1 -1
  80. package/lib/client.js +3 -4
  81. package/lib/client.js.map +1 -1
  82. package/lib/index.d.ts +1 -1
  83. package/lib/index.d.ts.map +1 -1
  84. package/lib/index.js.map +1 -1
  85. package/lib/legacy.d.ts +1 -0
  86. package/lib/localReference.d.ts.map +1 -1
  87. package/lib/localReference.js +0 -2
  88. package/lib/localReference.js.map +1 -1
  89. package/lib/mergeTree.d.ts +1 -30
  90. package/lib/mergeTree.d.ts.map +1 -1
  91. package/lib/mergeTree.js +132 -168
  92. package/lib/mergeTree.js.map +1 -1
  93. package/lib/mergeTreeNodes.d.ts +16 -1
  94. package/lib/mergeTreeNodes.d.ts.map +1 -1
  95. package/lib/mergeTreeNodes.js +5 -2
  96. package/lib/mergeTreeNodes.js.map +1 -1
  97. package/lib/partialLengths.d.ts.map +1 -1
  98. package/lib/partialLengths.js +8 -54
  99. package/lib/partialLengths.js.map +1 -1
  100. package/lib/properties.d.ts.map +1 -1
  101. package/lib/properties.js +0 -2
  102. package/lib/properties.js.map +1 -1
  103. package/lib/revertibles.d.ts.map +1 -1
  104. package/lib/revertibles.js +0 -14
  105. package/lib/revertibles.js.map +1 -1
  106. package/lib/segmentGroupCollection.d.ts.map +1 -1
  107. package/lib/segmentGroupCollection.js +0 -2
  108. package/lib/segmentGroupCollection.js.map +1 -1
  109. package/lib/segmentPropertiesManager.d.ts.map +1 -1
  110. package/lib/segmentPropertiesManager.js +1 -3
  111. package/lib/segmentPropertiesManager.js.map +1 -1
  112. package/lib/snapshotLoader.d.ts.map +1 -1
  113. package/lib/snapshotLoader.js +1 -4
  114. package/lib/snapshotLoader.js.map +1 -1
  115. package/lib/snapshotV1.d.ts.map +1 -1
  116. package/lib/snapshotV1.js +1 -11
  117. package/lib/snapshotV1.js.map +1 -1
  118. package/lib/snapshotlegacy.d.ts.map +1 -1
  119. package/lib/snapshotlegacy.js +0 -1
  120. package/lib/snapshotlegacy.js.map +1 -1
  121. package/lib/sortedSegmentSet.d.ts +0 -1
  122. package/lib/sortedSegmentSet.d.ts.map +1 -1
  123. package/lib/sortedSegmentSet.js +1 -9
  124. package/lib/sortedSegmentSet.js.map +1 -1
  125. package/lib/sortedSet.d.ts.map +1 -1
  126. package/lib/sortedSet.js +0 -4
  127. package/lib/sortedSet.js.map +1 -1
  128. package/lib/test/client.conflictFarm.spec.d.ts.map +1 -1
  129. package/lib/test/client.conflictFarm.spec.js +37 -28
  130. package/lib/test/client.conflictFarm.spec.js.map +1 -1
  131. package/lib/test/client.replay.spec.js +1 -1
  132. package/lib/test/client.replay.spec.js.map +1 -1
  133. package/lib/test/mergeTreeOperationRunner.d.ts +2 -1
  134. package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
  135. package/lib/test/mergeTreeOperationRunner.js +30 -12
  136. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  137. package/lib/test/obliterate.spec.js +55 -0
  138. package/lib/test/obliterate.spec.js.map +1 -1
  139. package/lib/test/reconnectHelper.d.ts +0 -1
  140. package/lib/test/reconnectHelper.d.ts.map +1 -1
  141. package/lib/test/reconnectHelper.js +1 -1
  142. package/lib/test/reconnectHelper.js.map +1 -1
  143. package/lib/test/testClientLogger.d.ts.map +1 -1
  144. package/lib/test/testClientLogger.js +18 -8
  145. package/lib/test/testClientLogger.js.map +1 -1
  146. package/lib/tsdoc-metadata.json +1 -1
  147. package/lib/zamboni.d.ts.map +1 -1
  148. package/lib/zamboni.js +0 -4
  149. package/lib/zamboni.js.map +1 -1
  150. package/package.json +22 -21
  151. package/src/attributionCollection.ts +14 -42
  152. package/src/client.ts +8 -9
  153. package/src/index.ts +1 -0
  154. package/src/localReference.ts +1 -3
  155. package/src/mergeTree.ts +185 -208
  156. package/src/mergeTreeNodes.ts +22 -3
  157. package/src/partialLengths.ts +23 -68
  158. package/src/properties.ts +1 -3
  159. package/src/revertibles.ts +7 -21
  160. package/src/segmentGroupCollection.ts +1 -3
  161. package/src/segmentPropertiesManager.ts +0 -1
  162. package/src/snapshotLoader.ts +2 -4
  163. package/src/snapshotV1.ts +5 -15
  164. package/src/snapshotlegacy.ts +1 -2
  165. package/src/sortedSegmentSet.ts +3 -10
  166. package/src/sortedSet.ts +2 -6
  167. package/src/zamboni.ts +4 -8
  168. package/tsconfig.json +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tITelemetryLoggerExt,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { NonCollabClient, UnassignedSequenceNumber } from \"./constants.js\";\nimport { MergeTree } from \"./mergeTree.js\";\nimport { ISegment } from \"./mergeTreeNodes.js\";\nimport { matchProperties } from \"./properties.js\";\nimport {\n\tJsonSegmentSpecs,\n\tMergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks.js\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegment[] | undefined;\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Snapshot\" });\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegment[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegment[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\t// TODO Non null asserting, why is this not null?\n\t\t\tconst pseg = allSegments[startIndex + segCount]!;\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0 || this.mergeTree.attributionPolicy?.isAttached\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\t// Messages used to have a \"term\" property which has since been removed.\n\t\t\t// It is benign so it doesn't really need to be deleted here, but doing so permits snapshot tests\n\t\t\t// to pass with an exact match (and matching the updated definition of ISequencedDocumentMessage).\n\t\t\tfor (const message of catchUpMsgs) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\t\t\tdelete (message as any).term;\n\t\t\t}\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync(): ISegment[] {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tthis.seq = collabWindow.minSeq;\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(\n\t\t\t\tthis.mergeTree.collabWindow.minSeq,\n\t\t\t\tNonCollabClient,\n\t\t\t),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tlet originalSegments = 0;\n\n\t\tconst segs: ISegment[] = [];\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (\n\t\t\tsegment: ISegment,\n\t\t\tpos: number,\n\t\t\trefSeq: number,\n\t\t\tclientId: number,\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined,\n\t\t): boolean => {\n\t\t\tif (\n\t\t\t\tsegment.seq !== UnassignedSequenceNumber &&\n\t\t\t\tsegment.seq! <= this.seq! &&\n\t\t\t\t(segment.removedSeq === undefined ||\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber ||\n\t\t\t\t\tsegment.removedSeq > this.seq!)\n\t\t\t) {\n\t\t\t\toriginalSegments += 1;\n\t\t\t\tif (prev?.canAppend(segment) && matchProperties(prev.properties, segment.properties)) {\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tsegs.push(prev);\n\t\t\t\t\t}\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);\n\t\tif (prev) {\n\t\t\tsegs.push(prev);\n\t\t}\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\tsegment.properties = undefined;\n\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t}\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// To reduce potential spam from this telemetry, we sample only a small\n\t\t// percentage of summaries\n\t\tif (Math.abs(originalSegments - segs.length) > 500 && Math.random() < 0.005) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"MergeTreeLegacySummarizeSegmentCount\",\n\t\t\t\toriginalSegments,\n\t\t\t\tsegmentsAfterCombine: segs.length,\n\t\t\t\tsegmentsLen: this.segments.length,\n\t\t\t});\n\t\t}\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tITelemetryLoggerExt,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { NonCollabClient, UnassignedSequenceNumber } from \"./constants.js\";\nimport { MergeTree } from \"./mergeTree.js\";\nimport { ISegment } from \"./mergeTreeNodes.js\";\nimport { matchProperties } from \"./properties.js\";\nimport {\n\tJsonSegmentSpecs,\n\tMergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks.js\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegment[] | undefined;\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Snapshot\" });\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegment[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegment[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0 || this.mergeTree.attributionPolicy?.isAttached\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\t// Messages used to have a \"term\" property which has since been removed.\n\t\t\t// It is benign so it doesn't really need to be deleted here, but doing so permits snapshot tests\n\t\t\t// to pass with an exact match (and matching the updated definition of ISequencedDocumentMessage).\n\t\t\tfor (const message of catchUpMsgs) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\t\t\tdelete (message as any).term;\n\t\t\t}\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync(): ISegment[] {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tthis.seq = collabWindow.minSeq;\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(\n\t\t\t\tthis.mergeTree.collabWindow.minSeq,\n\t\t\t\tNonCollabClient,\n\t\t\t),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tlet originalSegments = 0;\n\n\t\tconst segs: ISegment[] = [];\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (\n\t\t\tsegment: ISegment,\n\t\t\tpos: number,\n\t\t\trefSeq: number,\n\t\t\tclientId: number,\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined,\n\t\t): boolean => {\n\t\t\tif (\n\t\t\t\tsegment.seq !== UnassignedSequenceNumber &&\n\t\t\t\tsegment.seq! <= this.seq! &&\n\t\t\t\t(segment.removedSeq === undefined ||\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber ||\n\t\t\t\t\tsegment.removedSeq > this.seq!)\n\t\t\t) {\n\t\t\t\toriginalSegments += 1;\n\t\t\t\tif (prev?.canAppend(segment) && matchProperties(prev.properties, segment.properties)) {\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tsegs.push(prev);\n\t\t\t\t\t}\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);\n\t\tif (prev) {\n\t\t\tsegs.push(prev);\n\t\t}\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\tsegment.properties = undefined;\n\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t}\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// To reduce potential spam from this telemetry, we sample only a small\n\t\t// percentage of summaries\n\t\tif (Math.abs(originalSegments - segs.length) > 500 && Math.random() < 0.005) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"MergeTreeLegacySummarizeSegmentCount\",\n\t\t\t\toriginalSegments,\n\t\t\t\tsegmentsAfterCombine: segs.length,\n\t\t\t\tsegmentsLen: this.segments.length,\n\t\t\t});\n\t\t}\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
@@ -22,7 +22,6 @@ export type SortedSegmentSetItem = ISegment | LocalReferencePosition | {
22
22
  * the segments changes. This invariant allows us to ensure the segments stay
23
23
  * ordered and unique, and that new segments can be inserted into that order.
24
24
  *
25
- * @deprecated This functionality was not meant to be exported and will be removed in a future release
26
25
  * @internal
27
26
  */
28
27
  export declare class SortedSegmentSet<T extends SortedSegmentSetItem = ISegment> extends SortedSet<T, string> {
@@ -1 +1 @@
1
- {"version":3,"file":"sortedSegmentSet.d.ts","sourceRoot":"","sources":["../src/sortedSegmentSet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC7B,QAAQ,GACR,sBAAsB,GACtB;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;GAYG;AAEH,qBAAa,gBAAgB,CAAC,CAAC,SAAS,oBAAoB,GAAG,QAAQ,CAAE,SAAQ,SAAS,CACzF,CAAC,EACD,MAAM,CACN;IACA,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM;IAmBjC,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CA2DvE"}
1
+ {"version":3,"file":"sortedSegmentSet.d.ts","sourceRoot":"","sources":["../src/sortedSegmentSet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC7B,QAAQ,GACR,sBAAsB,GACtB;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;GAWG;AAEH,qBAAa,gBAAgB,CAAC,CAAC,SAAS,oBAAoB,GAAG,QAAQ,CAAE,SAAQ,SAAS,CACzF,CAAC,EACD,MAAM,CACN;IACA,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM;IAmBjC,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CAqDvE"}
@@ -14,7 +14,6 @@ import { SortedSet } from "./sortedSet.js";
14
14
  * the segments changes. This invariant allows us to ensure the segments stay
15
15
  * ordered and unique, and that new segments can be inserted into that order.
16
16
  *
17
- * @deprecated This functionality was not meant to be exported and will be removed in a future release
18
17
  * @internal
19
18
  */
20
19
  // eslint-disable-next-line import/no-deprecated
@@ -46,8 +45,6 @@ export class SortedSegmentSet extends SortedSet {
46
45
  let index = -1;
47
46
  while (start <= end) {
48
47
  index = start + Math.floor((end - start) / 2);
49
- // TODO Non null asserting, why is this not null?
50
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
51
48
  const indexKey = this.getKey(this.keySortedItems[index]);
52
49
  if (indexKey > itemKey) {
53
50
  if (start === index) {
@@ -68,17 +65,12 @@ export class SortedSegmentSet extends SortedSet {
68
65
  if (item === this.keySortedItems[index]) {
69
66
  return { exists: true, index };
70
67
  }
71
- for (let b = index - 1;
72
- // TODO Non null asserting, why is this not null?
73
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
74
- b >= 0 && this.getKey(this.keySortedItems[b]) === itemKey; b--) {
68
+ for (let b = index - 1; b >= 0 && this.getKey(this.keySortedItems[b]) === itemKey; b--) {
75
69
  if (this.keySortedItems[b] === item) {
76
70
  return { exists: true, index: b };
77
71
  }
78
72
  }
79
73
  for (index + 1; index < this.keySortedItems.length &&
80
- // TODO Non null asserting, why is this not null?
81
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
82
74
  this.getKey(this.keySortedItems[index]) === itemKey; index++) {
83
75
  if (this.keySortedItems[index] === item) {
84
76
  return { exists: true, index };
@@ -1 +1 @@
1
- {"version":3,"file":"sortedSegmentSet.js","sourceRoot":"","sources":["../src/sortedSegmentSet.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 { LocalReferencePosition } from \"./localReference.js\";\nimport { ISegment } from \"./mergeTreeNodes.js\";\n// eslint-disable-next-line import/no-deprecated\nimport { SortedSet } from \"./sortedSet.js\";\n\n/**\n * @deprecated This functionality was not meant to be exported and will be removed in a future release\n * @internal\n */\nexport type SortedSegmentSetItem =\n\t| ISegment\n\t| LocalReferencePosition\n\t| { readonly segment: ISegment };\n\n/**\n * Stores a unique and sorted set of segments, or objects with segments\n *\n * This differs from a normal sorted set in that the keys are not fixed.\n * The segments are sorted via their ordinals which can change as the merge tree is modified.\n * Even though the values of the ordinals can change their ordering and uniqueness cannot, so the order of a set of\n * segments ordered by their ordinals will always have the same order even if the ordinal values on\n * the segments changes. This invariant allows us to ensure the segments stay\n * ordered and unique, and that new segments can be inserted into that order.\n *\n * @deprecated This functionality was not meant to be exported and will be removed in a future release\n * @internal\n */\n// eslint-disable-next-line import/no-deprecated\nexport class SortedSegmentSet<T extends SortedSegmentSetItem = ISegment> extends SortedSet<\n\tT,\n\tstring\n> {\n\tprotected getKey(item: T): string {\n\t\tconst maybeRef = item as Partial<LocalReferencePosition>;\n\t\tif (maybeRef.getSegment !== undefined && maybeRef.isLeaf?.() === false) {\n\t\t\tconst lref = maybeRef as LocalReferencePosition;\n\t\t\t// If the reference position has no associated segment, assign it a sentinel value.\n\t\t\t// The particular value for comparison doesn't matter because `findItemPosition` tolerates\n\t\t\t// elements with duplicate keys (as it must, since local references use the same key as their segment).\n\t\t\t// All that matters is that it's consistent.\n\t\t\treturn lref.getSegment()?.ordinal ?? \"\";\n\t\t}\n\t\tconst maybeObject = item as { readonly segment: ISegment };\n\t\tif (maybeObject?.segment) {\n\t\t\treturn maybeObject.segment.ordinal;\n\t\t}\n\n\t\tconst maybeSegment = item as ISegment;\n\t\treturn maybeSegment.ordinal;\n\t}\n\n\tprotected findItemPosition(item: T): { exists: boolean; index: number } {\n\t\tif (this.keySortedItems.length === 0) {\n\t\t\treturn { exists: false, index: 0 };\n\t\t}\n\t\tlet start = 0;\n\t\tlet end = this.keySortedItems.length - 1;\n\t\tconst itemKey = this.getKey(item);\n\t\tlet index = -1;\n\n\t\twhile (start <= end) {\n\t\t\tindex = start + Math.floor((end - start) / 2);\n\t\t\t// TODO Non null asserting, why is this not null?\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst indexKey = this.getKey(this.keySortedItems[index]!);\n\t\t\tif (indexKey > itemKey) {\n\t\t\t\tif (start === index) {\n\t\t\t\t\treturn { exists: false, index };\n\t\t\t\t}\n\t\t\t\tend = index - 1;\n\t\t\t} else if (indexKey < itemKey) {\n\t\t\t\tif (index === end) {\n\t\t\t\t\treturn { exists: false, index: index + 1 };\n\t\t\t\t}\n\t\t\t\tstart = index + 1;\n\t\t\t} else if (indexKey === itemKey) {\n\t\t\t\t// at this point we've found the key of the item\n\t\t\t\t// so we need to find the index of the item instance\n\t\t\t\t//\n\t\t\t\tif (item === this.keySortedItems[index]) {\n\t\t\t\t\treturn { exists: true, index };\n\t\t\t\t}\n\t\t\t\tfor (\n\t\t\t\t\tlet b = index - 1;\n\t\t\t\t\t// TODO Non null asserting, why is this not null?\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tb >= 0 && this.getKey(this.keySortedItems[b]!) === itemKey;\n\t\t\t\t\tb--\n\t\t\t\t) {\n\t\t\t\t\tif (this.keySortedItems[b] === item) {\n\t\t\t\t\t\treturn { exists: true, index: b };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (\n\t\t\t\t\tindex + 1;\n\t\t\t\t\tindex < this.keySortedItems.length &&\n\t\t\t\t\t// TODO Non null asserting, why is this not null?\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tthis.getKey(this.keySortedItems[index]!) === itemKey;\n\t\t\t\t\tindex++\n\t\t\t\t) {\n\t\t\t\t\tif (this.keySortedItems[index] === item) {\n\t\t\t\t\t\treturn { exists: true, index };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { exists: false, index };\n\t\t\t}\n\t\t}\n\t\treturn { exists: false, index };\n\t}\n}\n"]}
1
+ {"version":3,"file":"sortedSegmentSet.js","sourceRoot":"","sources":["../src/sortedSegmentSet.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 { LocalReferencePosition } from \"./localReference.js\";\nimport { ISegment } from \"./mergeTreeNodes.js\";\n// eslint-disable-next-line import/no-deprecated\nimport { SortedSet } from \"./sortedSet.js\";\n\n/**\n * @deprecated This functionality was not meant to be exported and will be removed in a future release\n * @internal\n */\nexport type SortedSegmentSetItem =\n\t| ISegment\n\t| LocalReferencePosition\n\t| { readonly segment: ISegment };\n\n/**\n * Stores a unique and sorted set of segments, or objects with segments\n *\n * This differs from a normal sorted set in that the keys are not fixed.\n * The segments are sorted via their ordinals which can change as the merge tree is modified.\n * Even though the values of the ordinals can change their ordering and uniqueness cannot, so the order of a set of\n * segments ordered by their ordinals will always have the same order even if the ordinal values on\n * the segments changes. This invariant allows us to ensure the segments stay\n * ordered and unique, and that new segments can be inserted into that order.\n *\n * @internal\n */\n// eslint-disable-next-line import/no-deprecated\nexport class SortedSegmentSet<T extends SortedSegmentSetItem = ISegment> extends SortedSet<\n\tT,\n\tstring\n> {\n\tprotected getKey(item: T): string {\n\t\tconst maybeRef = item as Partial<LocalReferencePosition>;\n\t\tif (maybeRef.getSegment !== undefined && maybeRef.isLeaf?.() === false) {\n\t\t\tconst lref = maybeRef as LocalReferencePosition;\n\t\t\t// If the reference position has no associated segment, assign it a sentinel value.\n\t\t\t// The particular value for comparison doesn't matter because `findItemPosition` tolerates\n\t\t\t// elements with duplicate keys (as it must, since local references use the same key as their segment).\n\t\t\t// All that matters is that it's consistent.\n\t\t\treturn lref.getSegment()?.ordinal ?? \"\";\n\t\t}\n\t\tconst maybeObject = item as { readonly segment: ISegment };\n\t\tif (maybeObject?.segment) {\n\t\t\treturn maybeObject.segment.ordinal;\n\t\t}\n\n\t\tconst maybeSegment = item as ISegment;\n\t\treturn maybeSegment.ordinal;\n\t}\n\n\tprotected findItemPosition(item: T): { exists: boolean; index: number } {\n\t\tif (this.keySortedItems.length === 0) {\n\t\t\treturn { exists: false, index: 0 };\n\t\t}\n\t\tlet start = 0;\n\t\tlet end = this.keySortedItems.length - 1;\n\t\tconst itemKey = this.getKey(item);\n\t\tlet index = -1;\n\n\t\twhile (start <= end) {\n\t\t\tindex = start + Math.floor((end - start) / 2);\n\t\t\tconst indexKey = this.getKey(this.keySortedItems[index]);\n\t\t\tif (indexKey > itemKey) {\n\t\t\t\tif (start === index) {\n\t\t\t\t\treturn { exists: false, index };\n\t\t\t\t}\n\t\t\t\tend = index - 1;\n\t\t\t} else if (indexKey < itemKey) {\n\t\t\t\tif (index === end) {\n\t\t\t\t\treturn { exists: false, index: index + 1 };\n\t\t\t\t}\n\t\t\t\tstart = index + 1;\n\t\t\t} else if (indexKey === itemKey) {\n\t\t\t\t// at this point we've found the key of the item\n\t\t\t\t// so we need to find the index of the item instance\n\t\t\t\t//\n\t\t\t\tif (item === this.keySortedItems[index]) {\n\t\t\t\t\treturn { exists: true, index };\n\t\t\t\t}\n\t\t\t\tfor (\n\t\t\t\t\tlet b = index - 1;\n\t\t\t\t\tb >= 0 && this.getKey(this.keySortedItems[b]) === itemKey;\n\t\t\t\t\tb--\n\t\t\t\t) {\n\t\t\t\t\tif (this.keySortedItems[b] === item) {\n\t\t\t\t\t\treturn { exists: true, index: b };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (\n\t\t\t\t\tindex + 1;\n\t\t\t\t\tindex < this.keySortedItems.length &&\n\t\t\t\t\tthis.getKey(this.keySortedItems[index]) === itemKey;\n\t\t\t\t\tindex++\n\t\t\t\t) {\n\t\t\t\t\tif (this.keySortedItems[index] === item) {\n\t\t\t\t\t\treturn { exists: true, index };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { exists: false, index };\n\t\t\t}\n\t\t}\n\t\treturn { exists: false, index };\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"sortedSet.d.ts","sourceRoot":"","sources":["../src/sortedSet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,8BAAsB,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IAC3D,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC;IAElC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,EAAE,CAAM;IAE5C,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,KAAK,IAAI,SAAS,CAAC,EAAE,CAE/B;IAEM,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI;IAW7E,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IASxB,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAK5B,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CA8BvE"}
1
+ {"version":3,"file":"sortedSet.d.ts","sourceRoot":"","sources":["../src/sortedSet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,8BAAsB,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IAC3D,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC;IAElC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,EAAE,CAAM;IAE5C,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,KAAK,IAAI,SAAS,CAAC,EAAE,CAE/B;IAEM,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI;IAS7E,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IASxB,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAK5B,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CA4BvE"}
package/lib/sortedSet.js CHANGED
@@ -19,8 +19,6 @@ export class SortedSet {
19
19
  addOrUpdate(newItem, update) {
20
20
  const position = this.findItemPosition(newItem);
21
21
  if (position.exists) {
22
- // Non null asserting here because we know the item exists
23
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
24
22
  update?.(this.keySortedItems[position.index], newItem);
25
23
  }
26
24
  else {
@@ -49,8 +47,6 @@ export class SortedSet {
49
47
  let index = -1;
50
48
  while (start <= end) {
51
49
  index = start + Math.floor((end - start) / 2);
52
- // TODO Non null asserting, why is this not null?
53
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
54
50
  const indexKey = this.getKey(this.keySortedItems[index]);
55
51
  if (indexKey > itemKey) {
56
52
  if (start === index) {
@@ -1 +1 @@
1
- {"version":3,"file":"sortedSet.js","sourceRoot":"","sources":["../src/sortedSet.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\n/**\n * @deprecated This functionality was not meant to be exported and will be removed in a future release\n * @internal\n */\nexport abstract class SortedSet<T, U extends string | number> {\n\tprotected abstract getKey(t: T): U;\n\n\tprotected readonly keySortedItems: T[] = [];\n\n\tpublic get size(): number {\n\t\treturn this.keySortedItems.length;\n\t}\n\n\tpublic get items(): readonly T[] {\n\t\treturn this.keySortedItems;\n\t}\n\n\tpublic addOrUpdate(newItem: T, update?: (existingItem: T, newItem: T) => void): void {\n\t\tconst position = this.findItemPosition(newItem);\n\t\tif (position.exists) {\n\t\t\t// Non null asserting here because we know the item exists\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tupdate?.(this.keySortedItems[position.index]!, newItem);\n\t\t} else {\n\t\t\tthis.keySortedItems.splice(position.index, 0, newItem);\n\t\t}\n\t}\n\n\tpublic remove(item: T): boolean {\n\t\tconst position = this.findItemPosition(item);\n\t\tif (position.exists) {\n\t\t\tthis.keySortedItems.splice(position.index, 1);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic has(item: T): boolean {\n\t\tconst position = this.findItemPosition(item);\n\t\treturn position.exists;\n\t}\n\n\tprotected findItemPosition(item: T): { exists: boolean; index: number } {\n\t\tif (this.keySortedItems.length === 0) {\n\t\t\treturn { exists: false, index: 0 };\n\t\t}\n\t\tlet start = 0;\n\t\tlet end = this.keySortedItems.length - 1;\n\t\tconst itemKey = this.getKey(item);\n\t\tlet index = -1;\n\n\t\twhile (start <= end) {\n\t\t\tindex = start + Math.floor((end - start) / 2);\n\t\t\t// TODO Non null asserting, why is this not null?\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst indexKey = this.getKey(this.keySortedItems[index]!);\n\t\t\tif (indexKey > itemKey) {\n\t\t\t\tif (start === index) {\n\t\t\t\t\treturn { exists: false, index };\n\t\t\t\t}\n\t\t\t\tend = index - 1;\n\t\t\t} else if (indexKey < itemKey) {\n\t\t\t\tif (index === end) {\n\t\t\t\t\treturn { exists: false, index: index + 1 };\n\t\t\t\t}\n\t\t\t\tstart = index + 1;\n\t\t\t} else if (indexKey === itemKey) {\n\t\t\t\treturn { exists: true, index };\n\t\t\t}\n\t\t}\n\t\treturn { exists: false, index };\n\t}\n}\n"]}
1
+ {"version":3,"file":"sortedSet.js","sourceRoot":"","sources":["../src/sortedSet.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\n/**\n * @deprecated This functionality was not meant to be exported and will be removed in a future release\n * @internal\n */\nexport abstract class SortedSet<T, U extends string | number> {\n\tprotected abstract getKey(t: T): U;\n\n\tprotected readonly keySortedItems: T[] = [];\n\n\tpublic get size(): number {\n\t\treturn this.keySortedItems.length;\n\t}\n\n\tpublic get items(): readonly T[] {\n\t\treturn this.keySortedItems;\n\t}\n\n\tpublic addOrUpdate(newItem: T, update?: (existingItem: T, newItem: T) => void): void {\n\t\tconst position = this.findItemPosition(newItem);\n\t\tif (position.exists) {\n\t\t\tupdate?.(this.keySortedItems[position.index], newItem);\n\t\t} else {\n\t\t\tthis.keySortedItems.splice(position.index, 0, newItem);\n\t\t}\n\t}\n\n\tpublic remove(item: T): boolean {\n\t\tconst position = this.findItemPosition(item);\n\t\tif (position.exists) {\n\t\t\tthis.keySortedItems.splice(position.index, 1);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic has(item: T): boolean {\n\t\tconst position = this.findItemPosition(item);\n\t\treturn position.exists;\n\t}\n\n\tprotected findItemPosition(item: T): { exists: boolean; index: number } {\n\t\tif (this.keySortedItems.length === 0) {\n\t\t\treturn { exists: false, index: 0 };\n\t\t}\n\t\tlet start = 0;\n\t\tlet end = this.keySortedItems.length - 1;\n\t\tconst itemKey = this.getKey(item);\n\t\tlet index = -1;\n\n\t\twhile (start <= end) {\n\t\t\tindex = start + Math.floor((end - start) / 2);\n\t\t\tconst indexKey = this.getKey(this.keySortedItems[index]);\n\t\t\tif (indexKey > itemKey) {\n\t\t\t\tif (start === index) {\n\t\t\t\t\treturn { exists: false, index };\n\t\t\t\t}\n\t\t\t\tend = index - 1;\n\t\t\t} else if (indexKey < itemKey) {\n\t\t\t\tif (index === end) {\n\t\t\t\t\treturn { exists: false, index: index + 1 };\n\t\t\t\t}\n\t\t\t\tstart = index + 1;\n\t\t\t} else if (indexKey === itemKey) {\n\t\t\t\treturn { exists: true, index };\n\t\t\t}\n\t\t}\n\t\treturn { exists: false, index };\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"client.conflictFarm.spec.d.ts","sourceRoot":"","sources":["../../src/test/client.conflictFarm.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACN,YAAY,EACZ,+BAA+B,EAQ/B,MAAM,+BAA+B,CAAC;AAGvC,UAAU,mBAAoB,SAAQ,+BAA+B;IACpE,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;CACtB;AAID,eAAO,MAAM,YAAY,EAAE,mBAQ1B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,mBAO5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,mBAOzB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,mBAO3B,CAAC"}
1
+ {"version":3,"file":"client.conflictFarm.spec.d.ts","sourceRoot":"","sources":["../../src/test/client.conflictFarm.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACN,YAAY,EACZ,+BAA+B,EAS/B,MAAM,+BAA+B,CAAC;AAGvC,UAAU,mBAAoB,SAAQ,+BAA+B;IACpE,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;CACtB;AAID,eAAO,MAAM,YAAY,EAAE,mBAS1B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,mBAO5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,mBAOzB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,mBAO3B,CAAC"}
@@ -3,17 +3,18 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { describeFuzz, makeRandom } from "@fluid-private/stochastic-test-utils";
6
- import { annotateRange, doOverRange, generateClientNames, insertAtRefPos, removeRange, runMergeTreeOperationRunner, } from "./mergeTreeOperationRunner.js";
6
+ import { annotateRange, doOverRange, generateClientNames, insertAtRefPos, obliterateRange, removeRange, runMergeTreeOperationRunner, } from "./mergeTreeOperationRunner.js";
7
7
  import { TestClient } from "./testClient.js";
8
8
  const allOperations = [removeRange, annotateRange, insertAtRefPos];
9
9
  export const debugOptions = {
10
- minLength: { min: 1, max: 1 },
11
- clients: { min: 3, max: 3 },
12
- opsPerRoundRange: { min: 1, max: 100 },
13
- rounds: 1000,
10
+ minLength: { min: 1, max: 512 },
11
+ clients: { min: 1, max: 8 },
12
+ opsPerRoundRange: { min: 1, max: 128 },
13
+ rounds: 8,
14
14
  operations: allOperations,
15
15
  incrementalLog: true,
16
- growthFunc: (input) => input + 1,
16
+ growthFunc: (input) => input * 2,
17
+ // resultsFilePostfix: `conflict-farm-with-obliterate-2.3.0.json`,
17
18
  };
18
19
  export const defaultOptions = {
19
20
  minLength: { min: 1, max: 512 },
@@ -43,29 +44,37 @@ export const stressOptions = {
43
44
  const clientNames = generateClientNames();
44
45
  function runConflictFarmTests(opts, extraSeed) {
45
46
  doOverRange(opts.minLength, opts.growthFunc, (minLength) => {
46
- it(`ConflictFarm_${minLength}`, async () => {
47
- const random = makeRandom(0xdeadbeef, 0xfeedbed, minLength, extraSeed ?? 0);
48
- const testOpts = { ...opts };
49
- if (extraSeed) {
50
- testOpts.resultsFilePostfix ?? (testOpts.resultsFilePostfix = "");
51
- testOpts.resultsFilePostfix += extraSeed;
52
- }
53
- const clients = [new TestClient()];
54
- for (const [i, c] of clients.entries())
55
- c.startOrUpdateCollaboration(clientNames[i]);
56
- let seq = 0;
57
- while (clients.length < opts.clients.max) {
58
- for (const c of clients)
59
- c.updateMinSeq(seq);
60
- // Add double the number of clients each iteration
61
- const targetClients = Math.max(opts.clients.min, opts.growthFunc(clients.length));
62
- for (let cc = clients.length; cc < targetClients; cc++) {
63
- const newClient = await TestClient.createFromClientSnapshot(clients[0], clientNames[cc]);
64
- clients.push(newClient);
47
+ for (const { name, config } of [
48
+ {
49
+ name: "applyOpsDuringGeneration",
50
+ config: { ...opts, applyOpDuringGeneration: true },
51
+ },
52
+ {
53
+ name: "with obliterate",
54
+ config: {
55
+ ...opts,
56
+ operations: [...opts.operations, obliterateRange],
57
+ },
58
+ },
59
+ ])
60
+ it(`${name}: ConflictFarm_${minLength}`, async () => {
61
+ const random = makeRandom(0xdeadbeef, 0xfeedbed, minLength, extraSeed ?? 0);
62
+ const clients = [new TestClient({ mergeTreeEnableObliterate: true })];
63
+ for (const [i, c] of clients.entries())
64
+ c.startOrUpdateCollaboration(clientNames[i]);
65
+ let seq = 0;
66
+ while (clients.length < config.clients.max) {
67
+ for (const c of clients)
68
+ c.updateMinSeq(seq);
69
+ // Add double the number of clients each iteration
70
+ const targetClients = Math.max(config.clients.min, config.growthFunc(clients.length));
71
+ for (let cc = clients.length; cc < targetClients; cc++) {
72
+ const newClient = await TestClient.createFromClientSnapshot(clients[0], clientNames[cc]);
73
+ clients.push(newClient);
74
+ }
75
+ seq = runMergeTreeOperationRunner(random, seq, clients, minLength, config);
65
76
  }
66
- seq = runMergeTreeOperationRunner(random, seq, clients, minLength, opts);
67
- }
68
- }).timeout(30 * 10000);
77
+ }).timeout(30 * 10000);
69
78
  });
70
79
  }
71
80
  describeFuzz("MergeTree.Client", ({ testCount, isStress }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"client.conflictFarm.spec.js","sourceRoot":"","sources":["../../src/test/client.conflictFarm.spec.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 { describeFuzz, makeRandom } from \"@fluid-private/stochastic-test-utils\";\n\nimport {\n\tIConfigRange,\n\tIMergeTreeOperationRunnerConfig,\n\tTestOperation,\n\tannotateRange,\n\tdoOverRange,\n\tgenerateClientNames,\n\tinsertAtRefPos,\n\tremoveRange,\n\trunMergeTreeOperationRunner,\n} from \"./mergeTreeOperationRunner.js\";\nimport { TestClient } from \"./testClient.js\";\n\ninterface IConflictFarmConfig extends IMergeTreeOperationRunnerConfig {\n\tminLength: IConfigRange;\n\tclients: IConfigRange;\n}\n\nconst allOperations: TestOperation[] = [removeRange, annotateRange, insertAtRefPos];\n\nexport const debugOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 1 },\n\tclients: { min: 3, max: 3 },\n\topsPerRoundRange: { min: 1, max: 100 },\n\trounds: 1000,\n\toperations: allOperations,\n\tincrementalLog: true,\n\tgrowthFunc: (input: number) => input + 1,\n};\n\nexport const defaultOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 8 },\n\topsPerRoundRange: { min: 1, max: 128 },\n\trounds: 8,\n\toperations: allOperations,\n\tgrowthFunc: (input: number) => input * 2,\n};\n\nexport const longOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 32 },\n\topsPerRoundRange: { min: 1, max: 512 },\n\trounds: 32,\n\toperations: allOperations,\n\tgrowthFunc: (input: number) => input * 2,\n};\n\nexport const stressOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 32 },\n\topsPerRoundRange: { min: 1, max: 128 },\n\trounds: 32,\n\toperations: allOperations,\n\tgrowthFunc: (input: number) => input * 2,\n};\n\n// Generate a list of single character client names, support up to 69 clients\nconst clientNames = generateClientNames();\n\nfunction runConflictFarmTests(opts: IConflictFarmConfig, extraSeed?: number): void {\n\tdoOverRange(opts.minLength, opts.growthFunc, (minLength) => {\n\t\tit(`ConflictFarm_${minLength}`, async () => {\n\t\t\tconst random = makeRandom(0xdeadbeef, 0xfeedbed, minLength, extraSeed ?? 0);\n\t\t\tconst testOpts = { ...opts };\n\t\t\tif (extraSeed) {\n\t\t\t\ttestOpts.resultsFilePostfix ??= \"\";\n\t\t\t\ttestOpts.resultsFilePostfix += extraSeed;\n\t\t\t}\n\n\t\t\tconst clients: TestClient[] = [new TestClient()];\n\t\t\tfor (const [i, c] of clients.entries()) c.startOrUpdateCollaboration(clientNames[i]);\n\n\t\t\tlet seq = 0;\n\t\t\twhile (clients.length < opts.clients.max) {\n\t\t\t\tfor (const c of clients) c.updateMinSeq(seq);\n\n\t\t\t\t// Add double the number of clients each iteration\n\t\t\t\tconst targetClients = Math.max(opts.clients.min, opts.growthFunc(clients.length));\n\t\t\t\tfor (let cc = clients.length; cc < targetClients; cc++) {\n\t\t\t\t\tconst newClient = await TestClient.createFromClientSnapshot(\n\t\t\t\t\t\tclients[0],\n\t\t\t\t\t\tclientNames[cc],\n\t\t\t\t\t);\n\t\t\t\t\tclients.push(newClient);\n\t\t\t\t}\n\n\t\t\t\tseq = runMergeTreeOperationRunner(random, seq, clients, minLength, opts);\n\t\t\t}\n\t\t}).timeout(30 * 10000);\n\t});\n}\n\ndescribeFuzz(\"MergeTree.Client\", ({ testCount, isStress }) => {\n\tconst opts = isStress ? stressOptions : defaultOptions;\n\t// defaultOptions;\n\t// debugOptions;\n\t// longOptions;\n\n\tif (testCount > 1) {\n\t\tdoOverRange(\n\t\t\t{ min: 0, max: testCount - 1 },\n\t\t\t(x) => x + 1,\n\t\t\t(seed) => {\n\t\t\t\tdescribe(`with seed ${seed}`, () => {\n\t\t\t\t\trunConflictFarmTests(opts, seed);\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t} else {\n\t\trunConflictFarmTests(opts);\n\t}\n});\n"]}
1
+ {"version":3,"file":"client.conflictFarm.spec.js","sourceRoot":"","sources":["../../src/test/client.conflictFarm.spec.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 { describeFuzz, makeRandom } from \"@fluid-private/stochastic-test-utils\";\n\nimport {\n\tIConfigRange,\n\tIMergeTreeOperationRunnerConfig,\n\tTestOperation,\n\tannotateRange,\n\tdoOverRange,\n\tgenerateClientNames,\n\tinsertAtRefPos,\n\tobliterateRange,\n\tremoveRange,\n\trunMergeTreeOperationRunner,\n} from \"./mergeTreeOperationRunner.js\";\nimport { TestClient } from \"./testClient.js\";\n\ninterface IConflictFarmConfig extends IMergeTreeOperationRunnerConfig {\n\tminLength: IConfigRange;\n\tclients: IConfigRange;\n}\n\nconst allOperations: TestOperation[] = [removeRange, annotateRange, insertAtRefPos];\n\nexport const debugOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 8 },\n\topsPerRoundRange: { min: 1, max: 128 },\n\trounds: 8,\n\toperations: allOperations,\n\tincrementalLog: true,\n\tgrowthFunc: (input: number) => input * 2,\n\t// resultsFilePostfix: `conflict-farm-with-obliterate-2.3.0.json`,\n};\n\nexport const defaultOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 8 },\n\topsPerRoundRange: { min: 1, max: 128 },\n\trounds: 8,\n\toperations: allOperations,\n\tgrowthFunc: (input: number) => input * 2,\n};\n\nexport const longOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 32 },\n\topsPerRoundRange: { min: 1, max: 512 },\n\trounds: 32,\n\toperations: allOperations,\n\tgrowthFunc: (input: number) => input * 2,\n};\n\nexport const stressOptions: IConflictFarmConfig = {\n\tminLength: { min: 1, max: 512 },\n\tclients: { min: 1, max: 32 },\n\topsPerRoundRange: { min: 1, max: 128 },\n\trounds: 32,\n\toperations: allOperations,\n\tgrowthFunc: (input: number) => input * 2,\n};\n\n// Generate a list of single character client names, support up to 69 clients\nconst clientNames = generateClientNames();\n\nfunction runConflictFarmTests(opts: IConflictFarmConfig, extraSeed?: number): void {\n\tdoOverRange(opts.minLength, opts.growthFunc, (minLength) => {\n\t\tfor (const { name, config } of [\n\t\t\t{\n\t\t\t\tname: \"applyOpsDuringGeneration\",\n\t\t\t\tconfig: { ...opts, applyOpDuringGeneration: true },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"with obliterate\",\n\t\t\t\tconfig: {\n\t\t\t\t\t...opts,\n\t\t\t\t\toperations: [...opts.operations, obliterateRange],\n\t\t\t\t},\n\t\t\t},\n\t\t])\n\t\t\tit(`${name}: ConflictFarm_${minLength}`, async () => {\n\t\t\t\tconst random = makeRandom(0xdeadbeef, 0xfeedbed, minLength, extraSeed ?? 0);\n\n\t\t\t\tconst clients: TestClient[] = [new TestClient({ mergeTreeEnableObliterate: true })];\n\t\t\t\tfor (const [i, c] of clients.entries()) c.startOrUpdateCollaboration(clientNames[i]);\n\n\t\t\t\tlet seq = 0;\n\t\t\t\twhile (clients.length < config.clients.max) {\n\t\t\t\t\tfor (const c of clients) c.updateMinSeq(seq);\n\n\t\t\t\t\t// Add double the number of clients each iteration\n\t\t\t\t\tconst targetClients = Math.max(\n\t\t\t\t\t\tconfig.clients.min,\n\t\t\t\t\t\tconfig.growthFunc(clients.length),\n\t\t\t\t\t);\n\t\t\t\t\tfor (let cc = clients.length; cc < targetClients; cc++) {\n\t\t\t\t\t\tconst newClient = await TestClient.createFromClientSnapshot(\n\t\t\t\t\t\t\tclients[0],\n\t\t\t\t\t\t\tclientNames[cc],\n\t\t\t\t\t\t);\n\t\t\t\t\t\tclients.push(newClient);\n\t\t\t\t\t}\n\n\t\t\t\t\tseq = runMergeTreeOperationRunner(random, seq, clients, minLength, config);\n\t\t\t\t}\n\t\t\t}).timeout(30 * 10000);\n\t});\n}\n\ndescribeFuzz(\"MergeTree.Client\", ({ testCount, isStress }) => {\n\tconst opts = isStress ? stressOptions : defaultOptions;\n\t// defaultOptions;\n\t// debugOptions;\n\t// longOptions;\n\n\tif (testCount > 1) {\n\t\tdoOverRange(\n\t\t\t{ min: 0, max: testCount - 1 },\n\t\t\t(x) => x + 1,\n\t\t\t(seed) => {\n\t\t\t\tdescribe(`with seed ${seed}`, () => {\n\t\t\t\t\trunConflictFarmTests(opts, seed);\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t} else {\n\t\trunConflictFarmTests(opts);\n\t}\n});\n"]}
@@ -15,7 +15,7 @@ describe("MergeTree.Client", () => {
15
15
  it(`Replay ${filePath}`, async () => {
16
16
  const file = JSON.parse(fs.readFileSync(`${replayResultsPath}/${filePath}`).toString());
17
17
  const msgClients = new Map();
18
- const originalClient = new TestClient();
18
+ const originalClient = new TestClient({ mergeTreeEnableObliterate: true });
19
19
  msgClients.set("A", { client: originalClient, msgs: [] });
20
20
  originalClient.insertTextLocal(0, file[0].initialText);
21
21
  originalClient.startOrUpdateCollaboration("A");
@@ -1 +1 @@
1
- {"version":3,"file":"client.replay.spec.js","sourceRoot":"","sources":["../../src/test/client.replay.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6DAA6D;AAE7D,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAI9B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAgB,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAe,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IACjC,KAAK,MAAM,QAAQ,IAAI,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC1D,EAAE,CAAC,UAAU,QAAQ,EAAE,EAAE,KAAK,IAAI,EAAE;YACnC,MAAM,IAAI,GAAkB,IAAI,CAAC,KAAK,CACrC,EAAE,CAAC,YAAY,CAAC,GAAG,iBAAiB,IAAI,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAC7C,CAAC;YACnB,MAAM,UAAU,GAAG,IAAI,GAAG,EAGvB,CAAC;YACJ,MAAM,cAAc,GAAG,IAAI,UAAU,EAAE,CAAC;YACxC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1D,cAAc,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YACvD,cAAc,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC;YAC/C,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;gBAC1B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBAC9B,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;oBACxD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACnC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,wBAAwB,CACvD,cAAc,EACd,GAAG,CAAC,QAAQ,CACZ,CAAC;wBACF,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;oBACpD,CAAC;gBACF,CAAC;YACF,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;gBAC1B,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;gBACrF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACtC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,8BAA8B,CAAC,CAAC;gBACnF,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBAC9B,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,QAAS,CAAE,CAAC;oBACjD,OACC,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;wBACzB,GAAG,CAAC,uBAAuB,GAAG,SAAS,CAAC,MAAM,CAAC,aAAa,EAAE,EAC7D,CAAC;wBACF,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAG,CAAC,CAAC;oBACpD,CAAC;oBACD,MAAM,EAAE,GAAG,GAAG,CAAC,QAAwB,CAAC;oBACxC,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAChC,EAAE,CAAC,IAAI,KAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAC7D,CAAC;oBACF,KAAK,MAAM,EAAE,IAAI,UAAU;wBAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnD,CAAC;gBAED,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;oBAC7B,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC9B,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAG,CAAC,CAAC;oBAC5C,CAAC;gBACF,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACjC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,6BAA6B,CAAC,CAAC;gBAC5E,MAAM,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;QACF,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IACxB,CAAC;AACF,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport assert from \"node:assert\";\nimport * as fs from \"node:fs\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { createGroupOp } from \"../opBuilder.js\";\nimport { IMergeTreeOp, MergeTreeDeltaType } from \"../ops.js\";\n\nimport { ReplayGroup, replayResultsPath } from \"./mergeTreeOperationRunner.js\";\nimport { TestClient } from \"./testClient.js\";\nimport { TestClientLogger } from \"./testClientLogger.js\";\n\ndescribe(\"MergeTree.Client\", () => {\n\tfor (const filePath of fs.readdirSync(replayResultsPath)) {\n\t\tit(`Replay ${filePath}`, async () => {\n\t\t\tconst file: ReplayGroup[] = JSON.parse(\n\t\t\t\tfs.readFileSync(`${replayResultsPath}/${filePath}`).toString(),\n\t\t\t) as ReplayGroup[];\n\t\t\tconst msgClients = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ client: TestClient; msgs: ISequencedDocumentMessage[] }\n\t\t\t>();\n\t\t\tconst originalClient = new TestClient();\n\t\t\tmsgClients.set(\"A\", { client: originalClient, msgs: [] });\n\t\t\toriginalClient.insertTextLocal(0, file[0].initialText);\n\t\t\toriginalClient.startOrUpdateCollaboration(\"A\");\n\t\t\tfor (const group of file) {\n\t\t\t\tfor (const msg of group.msgs) {\n\t\t\t\t\tassert(msg.clientId, \"expected clientId to be defined\");\n\t\t\t\t\tif (!msgClients.has(msg.clientId)) {\n\t\t\t\t\t\tconst client = await TestClient.createFromClientSnapshot(\n\t\t\t\t\t\t\toriginalClient,\n\t\t\t\t\t\t\tmsg.clientId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmsgClients.set(msg.clientId, { client, msgs: [] });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const group of file) {\n\t\t\t\tconst logger = new TestClientLogger([...msgClients.values()].map((mc) => mc.client));\n\t\t\t\tconst initialText = logger.validate();\n\t\t\t\tassert.strictEqual(initialText, group.initialText, \"Initial text not as expected\");\n\t\t\t\tfor (const msg of group.msgs) {\n\t\t\t\t\tconst msgClient = msgClients.get(msg.clientId!)!;\n\t\t\t\t\twhile (\n\t\t\t\t\t\tmsgClient.msgs.length > 0 &&\n\t\t\t\t\t\tmsg.referenceSequenceNumber > msgClient.client.getCurrentSeq()\n\t\t\t\t\t) {\n\t\t\t\t\t\tmsgClient.client.applyMsg(msgClient.msgs.shift()!);\n\t\t\t\t\t}\n\t\t\t\t\tconst op = msg.contents as IMergeTreeOp;\n\t\t\t\t\tmsgClient.client.localTransaction(\n\t\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? op : createGroupOp(op),\n\t\t\t\t\t);\n\t\t\t\t\tfor (const mc of msgClients) mc[1].msgs.push(msg);\n\t\t\t\t}\n\n\t\t\t\tfor (const mc of msgClients) {\n\t\t\t\t\twhile (mc[1].msgs.length > 0) {\n\t\t\t\t\t\tmc[1].client.applyMsg(mc[1].msgs.shift()!);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst result = logger.validate();\n\t\t\t\tassert.strictEqual(result, group.resultText, \"Result text not as expected\");\n\t\t\t\tlogger.dispose();\n\t\t\t}\n\t\t}).timeout(30 * 10000);\n\t}\n});\n"]}
1
+ {"version":3,"file":"client.replay.spec.js","sourceRoot":"","sources":["../../src/test/client.replay.spec.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport assert from \"node:assert\";\nimport * as fs from \"node:fs\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { createGroupOp } from \"../opBuilder.js\";\nimport { IMergeTreeOp, MergeTreeDeltaType } from \"../ops.js\";\n\nimport { ReplayGroup, replayResultsPath } from \"./mergeTreeOperationRunner.js\";\nimport { TestClient } from \"./testClient.js\";\nimport { TestClientLogger } from \"./testClientLogger.js\";\n\ndescribe(\"MergeTree.Client\", () => {\n\tfor (const filePath of fs.readdirSync(replayResultsPath)) {\n\t\tit(`Replay ${filePath}`, async () => {\n\t\t\tconst file: ReplayGroup[] = JSON.parse(\n\t\t\t\tfs.readFileSync(`${replayResultsPath}/${filePath}`).toString(),\n\t\t\t) as ReplayGroup[];\n\t\t\tconst msgClients = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ client: TestClient; msgs: ISequencedDocumentMessage[] }\n\t\t\t>();\n\t\t\tconst originalClient = new TestClient({ mergeTreeEnableObliterate: true });\n\t\t\tmsgClients.set(\"A\", { client: originalClient, msgs: [] });\n\t\t\toriginalClient.insertTextLocal(0, file[0].initialText);\n\t\t\toriginalClient.startOrUpdateCollaboration(\"A\");\n\t\t\tfor (const group of file) {\n\t\t\t\tfor (const msg of group.msgs) {\n\t\t\t\t\tassert(msg.clientId, \"expected clientId to be defined\");\n\t\t\t\t\tif (!msgClients.has(msg.clientId)) {\n\t\t\t\t\t\tconst client = await TestClient.createFromClientSnapshot(\n\t\t\t\t\t\t\toriginalClient,\n\t\t\t\t\t\t\tmsg.clientId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmsgClients.set(msg.clientId, { client, msgs: [] });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const group of file) {\n\t\t\t\tconst logger = new TestClientLogger([...msgClients.values()].map((mc) => mc.client));\n\t\t\t\tconst initialText = logger.validate();\n\t\t\t\tassert.strictEqual(initialText, group.initialText, \"Initial text not as expected\");\n\t\t\t\tfor (const msg of group.msgs) {\n\t\t\t\t\tconst msgClient = msgClients.get(msg.clientId!)!;\n\t\t\t\t\twhile (\n\t\t\t\t\t\tmsgClient.msgs.length > 0 &&\n\t\t\t\t\t\tmsg.referenceSequenceNumber > msgClient.client.getCurrentSeq()\n\t\t\t\t\t) {\n\t\t\t\t\t\tmsgClient.client.applyMsg(msgClient.msgs.shift()!);\n\t\t\t\t\t}\n\t\t\t\t\tconst op = msg.contents as IMergeTreeOp;\n\t\t\t\t\tmsgClient.client.localTransaction(\n\t\t\t\t\t\top.type === MergeTreeDeltaType.GROUP ? op : createGroupOp(op),\n\t\t\t\t\t);\n\t\t\t\t\tfor (const mc of msgClients) mc[1].msgs.push(msg);\n\t\t\t\t}\n\n\t\t\t\tfor (const mc of msgClients) {\n\t\t\t\t\twhile (mc[1].msgs.length > 0) {\n\t\t\t\t\t\tmc[1].client.applyMsg(mc[1].msgs.shift()!);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst result = logger.validate();\n\t\t\t\tassert.strictEqual(result, group.resultText, \"Result text not as expected\");\n\t\t\t\tlogger.dispose();\n\t\t\t}\n\t\t}).timeout(30 * 10000);\n\t}\n});\n"]}
@@ -44,6 +44,7 @@ export interface IMergeTreeOperationRunnerConfig {
44
44
  readonly opsPerRoundRange: IConfigRange;
45
45
  readonly incrementalLog?: boolean;
46
46
  readonly operations: readonly TestOperation[];
47
+ readonly applyOpDuringGeneration?: boolean;
47
48
  growthFunc(input: number): number;
48
49
  resultsFilePostfix?: string;
49
50
  }
@@ -55,7 +56,7 @@ export interface ReplayGroup {
55
56
  }
56
57
  export declare const replayResultsPath: string;
57
58
  export declare function runMergeTreeOperationRunner(random: IRandom, startingSeq: number, clients: readonly TestClient[], minLength: number, config: IMergeTreeOperationRunnerConfig, apply?: ApplyMessagesFn): number;
58
- export declare function generateOperationMessagesForClients(random: IRandom, startingSeq: number, clients: readonly TestClient[], logger: TestClientLogger, opsPerRound: number, minLength: number, operations: readonly TestOperation[]): [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][];
59
+ export declare function generateOperationMessagesForClients(random: IRandom, startingSeq: number, clients: readonly TestClient[], logger: TestClientLogger, opsPerRound: number, minLength: number, operations: readonly TestOperation[], applyOpDuringGeneration?: boolean): [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][];
59
60
  export declare function generateClientNames(): string[];
60
61
  type ApplyMessagesFn = (startingSeq: number, messageData: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][], clients: readonly TestClient[], logger: TestClientLogger, random: IRandom) => number;
61
62
  export declare function applyMessages(startingSeq: number, messageData: [ISequencedDocumentMessage, SegmentGroup | SegmentGroup[]][], clients: readonly TestClient[], logger: TestClientLogger): number;
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTreeOperationRunner.d.ts","sourceRoot":"","sources":["../../src/test/mergeTreeOperationRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mergeTreeOperationRunner.d.ts","sourceRoot":"","sources":["../../src/test/mergeTreeOperationRunner.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@
6
6
  import { strict as assert } from "node:assert";
7
7
  import * as fs from "node:fs";
8
8
  import { walkAllChildSegments } from "../mergeTreeNodeWalk.js";
9
- import { toRemovalInfo } from "../mergeTreeNodes.js";
9
+ import { toMoveInfo, toRemovalInfo } from "../mergeTreeNodes.js";
10
10
  import { MergeTreeDeltaType, ReferenceType } from "../ops.js";
11
11
  import { TextSegment } from "../textSegment.js";
12
12
  import { _dirname } from "./dirname.cjs";
@@ -31,7 +31,8 @@ export const insertAtRefPos = (client, opStart, opEnd, random) => {
31
31
  if (segs.length > 0) {
32
32
  const text = client.longClientId.repeat(random.integer(1, 3));
33
33
  const seg = random.pick(segs);
34
- const lref = client.createLocalReferencePosition(seg, toRemovalInfo(seg) ? 0 : random.integer(0, seg.cachedLength - 1), toRemovalInfo(seg)
34
+ const movedOrRemoved = toRemovalInfo(seg) ?? toMoveInfo(seg);
35
+ const lref = client.createLocalReferencePosition(seg, movedOrRemoved ? 0 : random.integer(0, seg.cachedLength - 1), movedOrRemoved
35
36
  ? ReferenceType.SlideOnRemove
36
37
  : random.pick([
37
38
  ReferenceType.Simple,
@@ -117,6 +118,7 @@ export const replayResultsPath = `${_dirname}/../../src/test/results`;
117
118
  export function runMergeTreeOperationRunner(random, startingSeq, clients, minLength, config, apply = applyMessages) {
118
119
  let seq = startingSeq;
119
120
  const results = [];
121
+ let fakeTime = 1725916319097;
120
122
  doOverRange(config.opsPerRoundRange, config.growthFunc, (opsPerRound) => {
121
123
  if (config.incrementalLog) {
122
124
  console.log(`MinLength: ${minLength} Clients: ${clients.length} Ops: ${opsPerRound} Seq: ${seq}`);
@@ -124,14 +126,13 @@ export function runMergeTreeOperationRunner(random, startingSeq, clients, minLen
124
126
  for (let round = 0; round < config.rounds; round++) {
125
127
  const initialText = clients[0].getText();
126
128
  const logger = new TestClientLogger(clients, `Clients: ${clients.length} Ops: ${opsPerRound} Round: ${round}`);
127
- const messageData = generateOperationMessagesForClients(random, seq, clients, logger, opsPerRound, minLength, config.operations);
128
- const msgs = messageData.map((md) => md[0]);
129
- seq = apply(seq, messageData, clients, logger, random);
129
+ const messageData = generateOperationMessagesForClients(random, seq, clients, logger, opsPerRound, minLength, config.operations, config.applyOpDuringGeneration);
130
+ seq = apply(messageData[0][0].sequenceNumber - 1, messageData, clients, logger, random);
130
131
  const resultText = logger.validate();
131
132
  results.push({
132
133
  initialText,
133
134
  resultText,
134
- msgs,
135
+ msgs: messageData.map((md) => ({ ...md[0], timestamp: fakeTime++ })),
135
136
  seq,
136
137
  });
137
138
  logger.dispose();
@@ -139,18 +140,24 @@ export function runMergeTreeOperationRunner(random, startingSeq, clients, minLen
139
140
  });
140
141
  if (config.resultsFilePostfix !== undefined) {
141
142
  const resultsFilePath = `${replayResultsPath}/len_${minLength}-clients_${clients.length}-${config.resultsFilePostfix}`;
142
- fs.writeFileSync(resultsFilePath, JSON.stringify(results, undefined, 4));
143
+ fs.writeFileSync(resultsFilePath, JSON.stringify(results, undefined, "\t"));
143
144
  }
144
145
  return seq;
145
146
  }
146
- export function generateOperationMessagesForClients(random, startingSeq, clients, logger, opsPerRound, minLength, operations) {
147
+ export function generateOperationMessagesForClients(random, startingSeq, clients, logger, opsPerRound, minLength, operations, applyOpDuringGeneration) {
147
148
  const minimumSequenceNumber = startingSeq;
148
- let tempSeq = startingSeq * -1;
149
+ let runningSeq = startingSeq;
149
150
  const messages = [];
150
151
  for (let i = 0; i < opsPerRound; i++) {
151
152
  // pick a client greater than 0, client 0 only applies remote ops
152
153
  // and is our baseline
153
154
  const client = clients[random.integer(1, clients.length - 1)];
155
+ if (applyOpDuringGeneration === true && messages.length > 0 && random.bool()) {
156
+ const toApply = messages
157
+ .filter(([msg]) => msg.sequenceNumber > client.getCollabWindow().currentSeq)
158
+ .slice(0, random.integer(1, 3));
159
+ applyMessages(toApply[0][0].sequenceNumber - 1, toApply, [client], logger);
160
+ }
154
161
  const len = client.getLength();
155
162
  const sg = client.peekPendingSegmentGroups();
156
163
  let op;
@@ -173,7 +180,7 @@ export function generateOperationMessagesForClients(random, startingSeq, clients
173
180
  if (sg === client.peekPendingSegmentGroups()) {
174
181
  assert.notEqual(sg, client.peekPendingSegmentGroups(), `op created but segment group not enqueued.${logger}`);
175
182
  }
176
- const message = client.makeOpMessage(op, --tempSeq);
183
+ const message = client.makeOpMessage(op, ++runningSeq);
177
184
  message.minimumSequenceNumber = minimumSequenceNumber;
178
185
  messages.push([
179
186
  message,
@@ -181,6 +188,14 @@ export function generateOperationMessagesForClients(random, startingSeq, clients
181
188
  ]);
182
189
  }
183
190
  }
191
+ const maxProcessedSeq = Math.max(...clients.map((c) => c.getCollabWindow().currentSeq));
192
+ if (messages.length > 0) {
193
+ const index = messages.findIndex(([msg]) => msg.sequenceNumber === maxProcessedSeq);
194
+ if (index !== -1) {
195
+ const apply = messages.splice(0, index + 1);
196
+ applyMessages(apply[0][0].sequenceNumber - 1, apply, clients, logger);
197
+ }
198
+ }
184
199
  return messages;
185
200
  }
186
201
  export function generateClientNames() {
@@ -207,8 +222,11 @@ export function applyMessages(startingSeq, messageData, clients, logger) {
207
222
  for (let i = 0; i < messageData.length; i++) {
208
223
  const [message] = messageData[i];
209
224
  message.sequenceNumber = ++seq;
210
- for (const c of clients)
211
- c.applyMsg(message);
225
+ for (const c of clients) {
226
+ if (c.getCollabWindow().currentSeq < message.sequenceNumber) {
227
+ c.applyMsg(message);
228
+ }
229
+ }
212
230
  }
213
231
  }
214
232
  catch (error) {