@fluidframework/sequence 2.41.0-338401 → 2.42.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.
- package/CHANGELOG.md +8 -0
- package/dist/intervalCollection.d.ts +3 -7
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +38 -58
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalCollectionMapInterfaces.d.ts +1 -0
- package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/dist/intervalCollectionMapInterfaces.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/sequence.d.ts +2 -1
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +5 -2
- package/dist/sequence.js.map +1 -1
- package/lib/intervalCollection.d.ts +3 -7
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +38 -58
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalCollectionMapInterfaces.d.ts +1 -0
- package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/lib/intervalCollectionMapInterfaces.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/sequence.d.ts +2 -1
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +5 -2
- package/lib/sequence.js.map +1 -1
- package/package.json +18 -18
- package/src/intervalCollection.ts +46 -76
- package/src/intervalCollectionMapInterfaces.ts +1 -0
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +6 -2
package/lib/sequence.js
CHANGED
|
@@ -275,15 +275,18 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
275
275
|
/**
|
|
276
276
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.reSubmitCore}
|
|
277
277
|
*/
|
|
278
|
-
reSubmitCore(content, localOpMetadata) {
|
|
278
|
+
reSubmitCore(content, localOpMetadata, squash = false) {
|
|
279
279
|
const originalRefSeq = this.inFlightRefSeqs.shift();
|
|
280
280
|
assert(originalRefSeq !== undefined, 0x8bb /* Expected a recorded refSeq when resubmitting an op */);
|
|
281
281
|
this.useResubmitRefSeq(originalRefSeq, () => {
|
|
282
282
|
if (!this.intervalCollections.tryResubmitMessage(content, localOpMetadata)) {
|
|
283
|
-
this.submitSequenceMessage(this.client.regeneratePendingOp(content, localOpMetadata));
|
|
283
|
+
this.submitSequenceMessage(this.client.regeneratePendingOp(content, localOpMetadata, squash));
|
|
284
284
|
}
|
|
285
285
|
});
|
|
286
286
|
}
|
|
287
|
+
reSubmitSquashed(content, localOpMetadata) {
|
|
288
|
+
this.reSubmitCore(content, localOpMetadata, true);
|
|
289
|
+
}
|
|
287
290
|
/**
|
|
288
291
|
* Revert an op
|
|
289
292
|
*/
|
package/lib/sequence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../src/sequence.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 { bufferToString } from \"@fluid-internal/client-utils\";\nimport { IEventThisPlaceHolder } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIChannelAttributes,\n\tIFluidDataStoreRuntime,\n\tIChannelStorageService,\n} from \"@fluidframework/datastore-definitions/internal\";\nimport {\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tClient,\n\tIJSONSegment,\n\tIMergeTreeAnnotateMsg,\n\tIMergeTreeDeltaOp,\n\t// eslint-disable-next-line import/no-deprecated\n\tIMergeTreeGroupMsg,\n\t// eslint-disable-next-line import/no-deprecated\n\tIMergeTreeObliterateMsg,\n\tIMergeTreeOp,\n\tIMergeTreeRemoveMsg,\n\tIRelativePosition,\n\tISegment,\n\tISegmentAction,\n\tLocalReferencePosition,\n\tMergeTreeDeltaType,\n\tMergeTreeRevertibleDriver,\n\tPropertySet,\n\tReferencePosition,\n\tReferenceType,\n\tSlidingPreference,\n\tcreateAnnotateRangeOp,\n\t// eslint-disable-next-line import/no-deprecated\n\tcreateGroupOp,\n\tcreateInsertOp,\n\tcreateObliterateRangeOp,\n\tcreateRemoveRangeOp,\n\tmatchProperties,\n\ttype AdjustParams,\n\ttype InteriorSequencePlace,\n\ttype MapLike,\n} from \"@fluidframework/merge-tree/internal\";\nimport {\n\tISummaryTreeWithStats,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\tObjectStoragePartition,\n\tSummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils/internal\";\nimport {\n\tIFluidSerializer,\n\tISharedObjectEvents,\n\tSharedObject,\n\ttype ISharedObject,\n} from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tLoggingError,\n\tcreateChildLogger,\n\tcreateConfigBasedOptionsProxy,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport Deque from \"double-ended-queue\";\n\nimport { type ISequenceIntervalCollection } from \"./intervalCollection.js\";\nimport { IMapOperation, IntervalCollectionMap } from \"./intervalCollectionMap.js\";\nimport {\n\tIMapMessageLocalMetadata,\n\ttype SequenceOptions,\n} from \"./intervalCollectionMapInterfaces.js\";\nimport {\n\tSequenceDeltaEvent,\n\tSequenceDeltaEventClass,\n\tSequenceMaintenanceEvent,\n\tSequenceMaintenanceEventClass,\n} from \"./sequenceDeltaEvent.js\";\n\nconst snapshotFileName = \"header\";\nconst contentPath = \"content\";\n\n/**\n * Events emitted in response to changes to the sequence data.\n *\n * @remarks\n *\n * The following is the list of events emitted.\n *\n * ### \"sequenceDelta\"\n *\n * The sequenceDelta event is emitted when segments are inserted, annotated, or removed.\n *\n * #### Listener signature\n *\n * ```typescript\n * (event: SequenceDeltaEvent, target: IEventThisPlaceHolder) => void\n * ```\n * - `event` - Various information on the segments that were modified.\n *\n * - `target` - The sequence itself.\n *\n * ### \"maintenance\"\n *\n * The maintenance event is emitted when segments are modified during merge-tree maintenance.\n *\n * #### Listener signature\n *\n * ```typescript\n * (event: SequenceMaintenanceEvent, target: IEventThisPlaceHolder) => void\n * ```\n * - `event` - Various information on the segments that were modified.\n *\n * - `target` - The sequence itself.\n * @legacy\n * @alpha\n */\nexport interface ISharedSegmentSequenceEvents extends ISharedObjectEvents {\n\t(\n\t\tevent: \"createIntervalCollection\",\n\t\tlistener: (label: string, local: boolean, target: IEventThisPlaceHolder) => void,\n\t): void;\n\t(\n\t\tevent: \"sequenceDelta\",\n\t\tlistener: (event: SequenceDeltaEvent, target: IEventThisPlaceHolder) => void,\n\t): void;\n\t(\n\t\tevent: \"maintenance\",\n\t\tlistener: (event: SequenceMaintenanceEvent, target: IEventThisPlaceHolder) => void,\n\t): void;\n}\n\n/**\n * @legacy\n * @alpha\n */\nexport interface ISharedSegmentSequence<T extends ISegment>\n\textends ISharedObject<ISharedSegmentSequenceEvents>,\n\t\tMergeTreeRevertibleDriver {\n\t/**\n\t * Creates a `LocalReferencePosition` on this SharedString. If the refType does not include\n\t * ReferenceType.Transient, the returned reference will be added to the localRefs on the provided segment.\n\t * @param segment - Segment to add the local reference on\n\t * @param offset - Offset on the segment at which to place the local reference\n\t * @param refType - ReferenceType for the created local reference\n\t * @param properties - PropertySet to place on the created local reference\n\t */\n\tcreateLocalReferencePosition(\n\t\tsegment: T,\n\t\toffset: number,\n\t\trefType: ReferenceType,\n\t\tproperties: PropertySet | undefined,\n\t\tslidingPreference?: SlidingPreference,\n\t\tcanSlideToEndpoint?: boolean,\n\t): LocalReferencePosition;\n\n\t/**\n\t * Removes a `LocalReferencePosition` from this SharedString.\n\t */\n\tremoveLocalReferencePosition(\n\t\tlref: LocalReferencePosition,\n\t): LocalReferencePosition | undefined;\n\n\t/**\n\t * Returns the length of the current sequence for the client\n\t */\n\tgetLength(): number;\n\n\t/**\n\t * Returns the current position of a segment, and -1 if the segment\n\t * does not exist in this sequence\n\t * @param segment - The segment to get the position of\n\t */\n\tgetPosition(segment: ISegment): number;\n\n\t/**\n\t * Resolves a `ReferencePosition` into a character position using this client's perspective.\n\t *\n\t * Reference positions that point to a character that has been removed will\n\t * always return the position of the nearest non-removed character, regardless\n\t * of `ReferenceType`. To handle this case specifically, one may wish\n\t * to look at the segment returned by `ReferencePosition.getSegment`.\n\t */\n\tlocalReferencePositionToPosition(lref: ReferencePosition): number;\n\n\t/**\n\t * Walk the underlying segments of the sequence.\n\t * The walked segments may extend beyond the range if the segments cross the\n\t * ranges start or end boundaries.\n\t *\n\t * Set split range to true to ensure only segments within the range are walked.\n\t *\n\t * @param handler - The function to handle each segment. Traversal ends if\n\t * this function returns true.\n\t * @param start - Optional. The start of range walk.\n\t * @param end - Optional. The end of range walk\n\t * @param accum - Optional. An object that will be passed to the handler for accumulation\n\t * @param splitRange - Optional. Splits boundary segments on the range boundaries. Defaults to false.\n\t */\n\twalkSegments<TClientData>(\n\t\thandler: ISegmentAction<TClientData>,\n\t\tstart?: number,\n\t\tend?: number,\n\t\taccum?: TClientData,\n\t\tsplitRange?: boolean,\n\t): void;\n\n\t/**\n\t * Inserts a segment directly before a `ReferencePosition`.\n\t * @param refPos - The reference position to insert the segment at\n\t * @param segment - The segment to insert\n\t */\n\tinsertAtReferencePosition(pos: ReferencePosition, segment: T): void;\n\n\t/**\n\t * Finds the segment information (i.e. segment + offset) corresponding to a character position in the SharedString.\n\t * If the position is past the end of the string, `segment` and `offset` on the returned object may be undefined.\n\t * @param pos - Character position (index) into the current local view of the SharedString.\n\t */\n\tgetContainingSegment(pos: number): {\n\t\tsegment: T | undefined;\n\t\toffset: number | undefined;\n\t};\n\n\tgetPropertiesAtPosition(pos: number): PropertySet | undefined;\n\n\t/**\n\t * @returns An iterable object that enumerates the IntervalCollection labels.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * const iter = this.getIntervalCollectionKeys();\n\t * for (key of iter)\n\t * const collection = this.getIntervalCollection(key);\n\t * ...\n\t * ```\n\t */\n\tgetIntervalCollectionLabels(): IterableIterator<string>;\n\n\t/**\n\t * Retrieves the interval collection keyed on `label`. If no such interval collection exists,\n\t * creates one.\n\t */\n\tgetIntervalCollection(label: string): ISequenceIntervalCollection;\n\n\t/**\n\t * Obliterate is similar to remove, but differs in that segments concurrently\n\t * inserted into an obliterated range will also be removed.\n\t * Inserts are considered concurrent to an obliterate iff the insert op's seq is after the obliterate op's refSeq\n\t * and the insert's refSeq is before the obliterates seq.\n\t * Inserts made by the client which most recently obliterated a range containing the insert position\n\t * are not considered concurrent to any obliteration (the last client to obliterate gets the right to insert).\n\t *\n\t * The endpoints can either be inclusive or exclusive.\n\t * Exclusive endpoints allow the obliterated range to \"grow\" to include adjacent concurrently inserted segments on that side.\n\t *\n\t * @param start - The start of the range to obliterate.\n\t * Inclusive if side is Before or a number is provided.\n\t * @param end - The end of the range to obliterate. Inclusive if side is After.\n\t * If a number is provided it is treated as exclusive,\n\t * but the endpoint does not expand in order to preserve existing behavior.\n\t *\n\t * @example Given the initial state `\"|ABC>\"`,\n\t * `obliterateRange({ pos: 0, side: Side.After }, { pos: 4, side: Side.Before })` obliterates `\"ABC\"`, leaving only `\"|>\"`.\n\t * `insertFromSpec(1, { text: \"AAA\"})` would insert `\"AAA\"` before |, resulting in `\"|AAA>\"`.\n\t * If another client does the same thing but inserts `\"BBB\"` and gets sequenced later, all clients will eventually see `|BBB>`.\n\t */\n\tobliterateRange(\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void;\n\n\t/**\n\t * @returns The most recent sequence number which has been acked by the server and processed by this\n\t * SharedSegmentSequence.\n\t */\n\tgetCurrentSeq(): number;\n\n\t/**\n\t * Annotates the range with the provided properties\n\t *\n\t * @param start - The inclusive start position of the range to annotate\n\t * @param end - The exclusive end position of the range to annotate\n\t * @param props - The properties to annotate the range with\n\t *\n\t */\n\tannotateRange(start: number, end: number, props: PropertySet): void;\n\n\t/**\n\t * Annotates a specified range within the sequence by applying the provided adjustments.\n\t *\n\t * @param start - The inclusive start position of the range to annotate. This is a zero-based index.\n\t * @param end - The exclusive end position of the range to annotate. This is a zero-based index.\n\t * @param adjust - A map-like object specifying the properties to adjust. Each key-value pair represents a property and its corresponding adjustment to be applied over the range.\n\t * An adjustment is defined by an object containing a `delta` to be added to the current property value, and optional `min` and `max` constraints to limit the adjusted value.\n\t *\n\t * @remarks\n\t * The range is defined by the start and end positions, where the start position is inclusive and the end position is exclusive.\n\t * The properties provided in the adjust parameter will be applied to the specified range. Each adjustment modifies the current value of the property by adding the specified `value`.\n\t * If the current value is not a number, the `delta` will be summed with 0 to compute the new value. The optional `min` and `max` constraints are applied after the adjustment to ensure the final value falls within the specified bounds.\n\t */\n\tannotateAdjustRange(start: number, end: number, adjust: MapLike<AdjustParams>): void;\n\n\t/**\n\t * @param start - The inclusive start of the range to remove\n\t * @param end - The exclusive end of the range to remove\n\t */\n\tremoveRange(start: number, end: number): void;\n\n\t/**\n\t * Resolves a remote client's position against the local sequence\n\t * and returns the remote client's position relative to the local\n\t * sequence. The client ref seq must be above the minimum sequence number\n\t * or the return value will be undefined.\n\t * Generally this method is used in conjunction with signals which provide\n\t * point in time values for the below parameters, and is useful for things\n\t * like displaying user position. It should not be used with persisted values\n\t * as persisted values will quickly become invalid as the remoteClientRefSeq\n\t * moves below the minimum sequence number\n\t * @param remoteClientPosition - The remote client's position to resolve\n\t * @param remoteClientRefSeq - The reference sequence number of the remote client\n\t * @param remoteClientId - The client id of the remote client\n\t */\n\tresolveRemoteClientPosition(\n\t\tremoteClientPosition: number,\n\t\tremoteClientRefSeq: number,\n\t\tremoteClientId: string,\n\t): number | undefined;\n\n\t// #region APIs we might want to remove\n\t/**\n\t * Initializes the object as a local, non-shared object. This object can become shared after\n\t * it is attached to the document.\n\t * @privateRemarks\n\t * TODO: determine if this API (from SharedObject) is needed by users of the encapsulated API, declarative API or both,\n\t * and handle exposing it in a consistent way for all SharedObjects if needed.\n\t */\n\tinitializeLocal(): void;\n\n\t/**\n\t * @deprecated The ability to create group ops will be removed in an upcoming\n\t * release, as group ops are redundant with the native batching capabilities\n\t * of the runtime\n\t */\n\t// eslint-disable-next-line import/no-deprecated\n\tgroupOperation(groupOp: IMergeTreeGroupMsg): void;\n\n\tgetRangeExtentsOfPosition(pos: number): {\n\t\tposStart: number | undefined;\n\t\tposAfterEnd: number | undefined;\n\t};\n\n\t/**\n\t * Inserts a segment\n\t * @param start - The position to insert the segment at\n\t * @param spec - The segment to inserts spec\n\t */\n\tinsertFromSpec(pos: number, spec: IJSONSegment): void;\n\n\t/**\n\t * Given a position specified relative to a marker id, lookup the marker\n\t * and convert the position to a character position.\n\t * @param relativePos - Id of marker (may be indirect) and whether position is before or after marker.\n\t */\n\tposFromRelativePos(relativePos: IRelativePosition): number;\n\n\t// #endregion\n}\n\n/**\n * @internal\n */\nexport abstract class SharedSegmentSequence<T extends ISegment>\n\textends SharedObject<ISharedSegmentSequenceEvents>\n\timplements ISharedSegmentSequence<T>\n{\n\t/**\n\t * This is a safeguard to avoid problematic reentrancy of local ops. This type of scenario occurs if the user of SharedString subscribes\n\t * to the `sequenceDelta` event and uses the callback for a local op to submit further local ops.\n\t * Historically (before 2.0.0-internal.6.1.0), doing so would result in eventual consistency issues or a corrupted document.\n\t * These issues were fixed in #16815 which makes such reentrancy no different from applying the ops in order but not from within the change events,\n\t * but there is still little test coverage for reentrant scenarios.\n\t * Additionally, applications submitting ops from inside change events need to take extreme care that their data models also support reentrancy.\n\t * Since this is likely not the case, by default SharedString throws when encountering reentrant ops.\n\t *\n\t * An application using SharedString which explicitly wants to opt in to allowing reentrancy anyway can set `sharedStringPreventReentrancy`\n\t * on the data store options to `false`.\n\t */\n\tprotected guardReentrancy: <TRet>(callback: () => TRet) => TRet;\n\n\tprivate static createOpsFromDelta(event: SequenceDeltaEvent): IMergeTreeDeltaOp[] {\n\t\tconst ops: IMergeTreeDeltaOp[] = [];\n\t\tfor (const r of event.ranges) {\n\t\t\tswitch (event.deltaOperation) {\n\t\t\t\tcase MergeTreeDeltaType.ANNOTATE: {\n\t\t\t\t\tconst lastAnnotate = ops[ops.length - 1] as IMergeTreeAnnotateMsg;\n\t\t\t\t\tconst props: PropertySet = {};\n\t\t\t\t\tfor (const key of Object.keys(r.propertyDeltas)) {\n\t\t\t\t\t\tprops[key] = r.segment.properties?.[key] ?? null;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tlastAnnotate &&\n\t\t\t\t\t\tlastAnnotate.pos2 === r.position &&\n\t\t\t\t\t\tmatchProperties(lastAnnotate.props, props)\n\t\t\t\t\t) {\n\t\t\t\t\t\tlastAnnotate.pos2 += r.segment.cachedLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tops.push(\n\t\t\t\t\t\t\tcreateAnnotateRangeOp(r.position, r.position + r.segment.cachedLength, props),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MergeTreeDeltaType.INSERT:\n\t\t\t\t\tops.push(createInsertOp(r.position, r.segment.clone().toJSONObject()));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MergeTreeDeltaType.REMOVE: {\n\t\t\t\t\tconst lastRem = ops[ops.length - 1] as IMergeTreeRemoveMsg;\n\t\t\t\t\tif (lastRem?.pos1 === r.position) {\n\t\t\t\t\t\tassert(lastRem.pos2 !== undefined, 0x3ff /* pos2 should not be undefined here */);\n\t\t\t\t\t\tlastRem.pos2 += r.segment.cachedLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tops.push(createRemoveRangeOp(r.position, r.position + r.segment.cachedLength));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MergeTreeDeltaType.OBLITERATE: {\n\t\t\t\t\t// eslint-disable-next-line import/no-deprecated\n\t\t\t\t\tconst lastRem = ops[ops.length - 1] as IMergeTreeObliterateMsg;\n\t\t\t\t\tif (lastRem?.pos1 === r.position) {\n\t\t\t\t\t\tassert(lastRem.pos2 !== undefined, 0x874 /* pos2 should not be undefined here */);\n\t\t\t\t\t\tlastRem.pos2 += r.segment.cachedLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tops.push(createObliterateRangeOp(r.position, r.position + r.segment.cachedLength));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t}\n\t\t}\n\t\treturn ops;\n\t}\n\n\t/**\n\t * Note: this field only provides a lower-bound on the reference sequence numbers for in-flight ops.\n\t * The exact reason isn't understood, but some e2e tests suggest that the runtime may sometimes process\n\t * incoming leave/join ops before putting an op that this DDS submits over the wire.\n\t *\n\t * E.g. SharedString submits an op while deltaManager has lastSequenceNumber = 10, but before the runtime\n\t * puts this op over the wire, it processes a client join/leave op with sequence number 11, so the referenceSequenceNumber\n\t * on the SharedString op is 11.\n\t *\n\t * The reference sequence numbers placed in this queue are also not accurate for stashed ops due to how the applyStashedOp\n\t * flow works at the runtime level. This is a legitimate bug, and AB#6602 tracks one way to fix it (stop reaching all the way\n\t * to deltaManager's lastSequenceNumber to obtain refSeq, instead leveraging some analogous notion on the container or datastore\n\t * runtime).\n\t */\n\tprivate readonly inFlightRefSeqs = new Deque<number>();\n\n\tprivate ongoingResubmitRefSeq: number | undefined;\n\n\t/**\n\t * Gets the reference sequence number (i.e. sequence number of the runtime's last processed op) for an op submitted\n\t * in the current context.\n\t *\n\t * This value can be optionally overridden using `useResubmitRefSeq`.\n\t * IntervalCollection's resubmit logic currently relies on preserving merge information from when the op was originally submitted,\n\t * even if the op is resubmitted more than once. Thus during resubmit, `inFlightRefSeqs` gets populated with the\n\t * original refSeq rather than the refSeq at the time of reconnection.\n\t *\n\t * @remarks - In some not fully understood cases, the runtime may process incoming ops before putting an op that this\n\t * DDS submits over the wire. See `inFlightRefSeqs` for more details.\n\t */\n\tprivate get currentRefSeq() {\n\t\treturn this.ongoingResubmitRefSeq ?? this.deltaManager.lastSequenceNumber;\n\t}\n\n\tprotected client: Client;\n\tprivate messagesSinceMSNChange: ISequencedDocumentMessage[] = [];\n\tprivate readonly intervalCollections: IntervalCollectionMap;\n\tconstructor(\n\t\tdataStoreRuntime: IFluidDataStoreRuntime,\n\t\tpublic id: string,\n\t\tattributes: IChannelAttributes,\n\t\tpublic readonly segmentFromSpec: (spec: IJSONSegment) => ISegment,\n\t) {\n\t\tsuper(id, dataStoreRuntime, attributes, \"fluid_sequence_\");\n\n\t\tconst getMinInFlightRefSeq = () => this.inFlightRefSeqs.get(0);\n\t\tthis.guardReentrancy =\n\t\t\t(dataStoreRuntime.options.sharedStringPreventReentrancy ?? true)\n\t\t\t\t? ensureNoReentrancy\n\t\t\t\t: createReentrancyDetector((depth) => {\n\t\t\t\t\t\tif (totalReentrancyLogs > 0) {\n\t\t\t\t\t\t\ttotalReentrancyLogs--;\n\t\t\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t\t\t{ eventName: \"LocalOpReentry\", depth },\n\t\t\t\t\t\t\t\tnew LoggingError(reentrancyErrorMessage),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\tconst options = createConfigBasedOptionsProxy<SequenceOptions>(\n\t\t\tloggerToMonitoringContext(this.logger).config,\n\t\t\t\"Fluid.Sequence\",\n\t\t\t{\n\t\t\t\tmergeTreeEnableObliterate: (c, n) => c.getBoolean(n),\n\t\t\t\tmergeTreeEnableSidedObliterate: (c, n) => c.getBoolean(n),\n\t\t\t\tintervalStickinessEnabled: (c, n) => c.getBoolean(n),\n\t\t\t\tmergeTreeReferencesCanSlideToEndpoint: (c, n) => c.getBoolean(n),\n\t\t\t\tmergeTreeEnableAnnotateAdjust: (c, n) => c.getBoolean(n),\n\t\t\t},\n\t\t\tdataStoreRuntime.options,\n\t\t);\n\n\t\tthis.client = new Client(\n\t\t\tsegmentFromSpec,\n\t\t\tcreateChildLogger({\n\t\t\t\tlogger: this.logger,\n\t\t\t\tnamespace: \"SharedSegmentSequence.MergeTreeClient\",\n\t\t\t}),\n\t\t\toptions,\n\t\t\tgetMinInFlightRefSeq,\n\t\t);\n\n\t\tthis.client.prependListener(\"delta\", (opArgs, deltaArgs) => {\n\t\t\tconst event = new SequenceDeltaEventClass(opArgs, deltaArgs, this.client);\n\t\t\tif (event.isLocal && event.opArgs.rollback !== true) {\n\t\t\t\tthis.submitSequenceMessage(opArgs.op);\n\t\t\t}\n\t\t\tif (deltaArgs.deltaSegments.length > 0) {\n\t\t\t\tthis.emit(\"sequenceDelta\", event, this);\n\t\t\t}\n\t\t});\n\n\t\tthis.client.on(\"maintenance\", (args, opArgs) => {\n\t\t\tthis.emit(\n\t\t\t\t\"maintenance\",\n\t\t\t\tnew SequenceMaintenanceEventClass(opArgs, args, this.client),\n\t\t\t\tthis,\n\t\t\t);\n\t\t});\n\n\t\tthis.intervalCollections = new IntervalCollectionMap(\n\t\t\tthis.serializer,\n\t\t\tthis.handle,\n\t\t\t(op, localOpMetadata) => {\n\t\t\t\tif (!this.isAttached()) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.inFlightRefSeqs.push(this.currentRefSeq);\n\t\t\t\tthis.submitLocalMessage(op, localOpMetadata);\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\tpublic removeRange(start: number, end: number): void {\n\t\tthis.guardReentrancy(() => this.client.removeRangeLocal(start, end));\n\t}\n\n\tpublic obliterateRange(\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tthis.guardReentrancy(() => this.client.obliterateRangeLocal(start, end));\n\t}\n\n\t// eslint-disable-next-line import/no-deprecated\n\tpublic groupOperation(groupOp: IMergeTreeGroupMsg): void {\n\t\tthis.guardReentrancy(() => this.client.localTransaction(groupOp));\n\t}\n\n\tpublic getContainingSegment(pos: number): {\n\t\tsegment: T | undefined;\n\t\toffset: number | undefined;\n\t} {\n\t\treturn this.client.getContainingSegment<T>(pos);\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this.client.getLength();\n\t}\n\n\tpublic getPosition(segment: ISegment): number {\n\t\treturn this.client.getPosition(segment);\n\t}\n\n\tpublic annotateRange(start: number, end: number, props: PropertySet): void {\n\t\tthis.guardReentrancy(() => this.client.annotateRangeLocal(start, end, props));\n\t}\n\n\tpublic annotateAdjustRange(start: number, end: number, adjust: MapLike<AdjustParams>): void {\n\t\tthis.guardReentrancy(() => this.client.annotateAdjustRangeLocal(start, end, adjust));\n\t}\n\n\tpublic getPropertiesAtPosition(pos: number): PropertySet | undefined {\n\t\treturn this.client.getPropertiesAtPosition(pos);\n\t}\n\n\tpublic getRangeExtentsOfPosition(pos: number): {\n\t\tposStart: number | undefined;\n\t\tposAfterEnd: number | undefined;\n\t} {\n\t\treturn this.client.getRangeExtentsOfPosition(pos);\n\t}\n\n\tpublic createLocalReferencePosition(\n\t\tsegment: T,\n\t\toffset: number,\n\t\trefType: ReferenceType,\n\t\tproperties: PropertySet | undefined,\n\t\tslidingPreference?: SlidingPreference,\n\t\tcanSlideToEndpoint?: boolean,\n\t): LocalReferencePosition {\n\t\treturn this.client.createLocalReferencePosition(\n\t\t\tsegment,\n\t\t\toffset,\n\t\t\trefType,\n\t\t\tproperties,\n\t\t\tslidingPreference,\n\t\t\tcanSlideToEndpoint,\n\t\t);\n\t}\n\n\tpublic localReferencePositionToPosition(lref: ReferencePosition): number {\n\t\treturn this.client.localReferencePositionToPosition(lref);\n\t}\n\n\tpublic removeLocalReferencePosition(\n\t\tlref: LocalReferencePosition,\n\t): LocalReferencePosition | undefined {\n\t\treturn this.client.removeLocalReferencePosition(lref);\n\t}\n\n\tpublic resolveRemoteClientPosition(\n\t\tremoteClientPosition: number,\n\t\tremoteClientRefSeq: number,\n\t\tremoteClientId: string,\n\t): number | undefined {\n\t\treturn this.client.resolveRemoteClientPosition(\n\t\t\tremoteClientPosition,\n\t\t\tremoteClientRefSeq,\n\t\t\tremoteClientId,\n\t\t);\n\t}\n\n\tprivate submitSequenceMessage(message: IMergeTreeOp) {\n\t\tif (!this.isAttached()) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.inFlightRefSeqs.push(this.currentRefSeq);\n\n\t\tconst metadata = this.client.peekPendingSegmentGroups(\n\t\t\tmessage.type === MergeTreeDeltaType.GROUP ? message.ops.length : 1,\n\t\t);\n\n\t\tthis.submitLocalMessage(message, metadata);\n\t}\n\n\tpublic posFromRelativePos(relativePos: IRelativePosition): number {\n\t\treturn this.client.posFromRelativePos(relativePos);\n\t}\n\n\tpublic walkSegments<TClientData>(\n\t\thandler: ISegmentAction<TClientData>,\n\t\tstart?: number,\n\t\tend?: number,\n\t\taccum?: TClientData,\n\t\tsplitRange: boolean = false,\n\t): void {\n\t\tthis.client.walkSegments(handler, start, end, accum as TClientData, splitRange);\n\t}\n\n\tpublic getCurrentSeq(): number {\n\t\treturn this.client.getCurrentSeq();\n\t}\n\n\tpublic insertAtReferencePosition(pos: ReferencePosition, segment: T): void {\n\t\tthis.guardReentrancy(() => this.client.insertAtReferencePositionLocal(pos, segment));\n\t}\n\n\tpublic insertFromSpec(pos: number, spec: IJSONSegment): void {\n\t\tconst segment = this.segmentFromSpec(spec);\n\t\tthis.guardReentrancy(() => this.client.insertSegmentLocal(pos, segment));\n\t}\n\n\tpublic getIntervalCollection(label: string): ISequenceIntervalCollection {\n\t\treturn this.intervalCollections.get(label);\n\t}\n\n\tpublic getIntervalCollectionLabels(): IterableIterator<string> {\n\t\treturn this.intervalCollections.keys();\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.summarizeCore}\n\t */\n\tprotected summarizeCore(\n\t\tserializer: IFluidSerializer,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): ISummaryTreeWithStats {\n\t\tconst builder = new SummaryTreeBuilder();\n\n\t\t// conditionally write the interval collection blob\n\t\t// only if it has entries\n\t\tif (this.intervalCollections.size > 0) {\n\t\t\tbuilder.addBlob(snapshotFileName, this.intervalCollections.serialize(serializer));\n\t\t}\n\n\t\tbuilder.addWithStats(contentPath, this.summarizeMergeTree(serializer));\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\t/**\n\t * Runs serializer over the GC data for this SharedMatrix.\n\t * All the IFluidHandle's represent routes to other objects.\n\t */\n\tprotected processGCDataCore(serializer: IFluidSerializer) {\n\t\tif (this.intervalCollections.size > 0) {\n\t\t\tthis.intervalCollections.serialize(serializer);\n\t\t}\n\n\t\tthis.client.serializeGCData(this.handle, serializer);\n\t}\n\n\t/**\n\t * Replace the range specified from start to end with the provided segment\n\t * This is done by inserting the segment at the end of the range, followed\n\t * by removing the contents of the range\n\t * For a zero or reverse range (start \\>= end), insert at end do not remove anything\n\t * @param start - The start of the range to replace\n\t * @param end - The end of the range to replace\n\t * @param segment - The segment that will replace the range\n\t */\n\tprotected replaceRange(start: number, end: number, segment: ISegment): void {\n\t\t// Insert at the max end of the range when start > end, but still remove the range later\n\t\tconst insertIndex: number = Math.max(start, end);\n\n\t\t// Insert first, so local references can slide to the inserted seg if any\n\t\tconst insert = this.guardReentrancy(() =>\n\t\t\tthis.client.insertSegmentLocal(insertIndex, segment),\n\t\t);\n\n\t\tif (insert && start < end) {\n\t\t\tthis.removeRange(start, end);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.onConnect}\n\t */\n\tprotected onConnect() {\n\t\t// Update merge tree collaboration information with new client ID and then resend pending ops\n\t\tthis.client.startOrUpdateCollaboration(this.runtime.clientId);\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.onDisconnect}\n\t */\n\tprotected onDisconnect() {}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.reSubmitCore}\n\t */\n\tprotected reSubmitCore(content: any, localOpMetadata: unknown) {\n\t\tconst originalRefSeq = this.inFlightRefSeqs.shift();\n\t\tassert(\n\t\t\toriginalRefSeq !== undefined,\n\t\t\t0x8bb /* Expected a recorded refSeq when resubmitting an op */,\n\t\t);\n\t\tthis.useResubmitRefSeq(originalRefSeq, () => {\n\t\t\tif (\n\t\t\t\t!this.intervalCollections.tryResubmitMessage(\n\t\t\t\t\tcontent,\n\t\t\t\t\tlocalOpMetadata as IMapMessageLocalMetadata,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthis.submitSequenceMessage(\n\t\t\t\t\tthis.client.regeneratePendingOp(content as IMergeTreeOp, localOpMetadata),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Revert an op\n\t */\n\tprotected rollback(content: any, localOpMetadata: unknown): void {\n\t\tconst originalRefSeq = this.inFlightRefSeqs.pop();\n\t\tassert(\n\t\t\toriginalRefSeq !== undefined,\n\t\t\t0xb7f /* Expected a recorded refSeq when rolling back an op */,\n\t\t);\n\n\t\tif (!this.intervalCollections.tryRollback(content, localOpMetadata)) {\n\t\t\tthis.client.rollback(content, localOpMetadata);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}\n\t */\n\tprotected async loadCore(storage: IChannelStorageService) {\n\t\tif (await storage.contains(snapshotFileName)) {\n\t\t\tconst blob = await storage.readBlob(snapshotFileName);\n\t\t\tconst header = bufferToString(blob, \"utf8\");\n\t\t\tthis.intervalCollections.populate(header);\n\t\t}\n\n\t\ttry {\n\t\t\t// this will load the header, and return a promise\n\t\t\t// that will resolve when the body is loaded\n\t\t\t// and the catchup ops are available.\n\t\t\tconst { catchupOpsP } = await this.client.load(\n\t\t\t\tthis.runtime,\n\t\t\t\tnew ObjectStoragePartition(storage, contentPath),\n\t\t\t\tthis.serializer,\n\t\t\t);\n\n\t\t\t// process the catch up ops, and finishing the loading process\n\t\t\t(await catchupOpsP).forEach((m) => {\n\t\t\t\tconst collabWindow = this.client.getCollabWindow();\n\t\t\t\tif (\n\t\t\t\t\tm.minimumSequenceNumber < collabWindow.minSeq ||\n\t\t\t\t\tm.referenceSequenceNumber < collabWindow.minSeq ||\n\t\t\t\t\tm.sequenceNumber <= collabWindow.minSeq ||\n\t\t\t\t\t// sequenceNumber could be the same if messages are part of a grouped batch\n\t\t\t\t\tm.sequenceNumber < collabWindow.currentSeq\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid catchup operations in snapshot: ${JSON.stringify({\n\t\t\t\t\t\t\top: {\n\t\t\t\t\t\t\t\tseq: m.sequenceNumber,\n\t\t\t\t\t\t\t\tminSeq: m.minimumSequenceNumber,\n\t\t\t\t\t\t\t\trefSeq: m.referenceSequenceNumber,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcollabWindow: {\n\t\t\t\t\t\t\t\tseq: collabWindow.currentSeq,\n\t\t\t\t\t\t\t\tminSeq: collabWindow.minSeq,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.processMergeTreeMsg(m);\n\t\t\t});\n\n\t\t\t// Initialize the interval collections\n\t\t\tthis.initializeIntervalCollections();\n\t\t} catch (error) {\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"SequenceLoadFailed\" }, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.processCore}\n\t */\n\tprotected processCore(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t) {\n\t\tif (local) {\n\t\t\tconst recordedRefSeq = this.inFlightRefSeqs.shift();\n\t\t\tassert(recordedRefSeq !== undefined, 0x8bc /* No pending recorded refSeq found */);\n\t\t\t// TODO: AB#7076: Some equivalent assert should be enabled. This fails some e2e stashed op tests because\n\t\t\t// the deltaManager may have seen more messages than the runtime has processed while amidst the stashed op\n\t\t\t// flow, so e.g. when `applyStashedOp` is called and the DDS is put in a state where it expects an ack for\n\t\t\t// one of its messages, the delta manager has actually already seen subsequent messages from collaborators\n\t\t\t// which the in-flight message is concurrent to.\n\t\t\t// See \"handles stashed ops created on top of sequenced local ops\" for one such test case.\n\t\t\t// assert(recordedRefSeq <= message.referenceSequenceNumber, \"RefSeq mismatch\");\n\t\t}\n\n\t\tassert(\n\t\t\tmessage.type === MessageType.Operation,\n\t\t\t0x073 /* \"Sequence message not operation\" */,\n\t\t);\n\n\t\tconst handled = this.intervalCollections.tryProcessMessage(\n\t\t\tmessage.contents as IMapOperation,\n\t\t\tlocal,\n\t\t\tmessage,\n\t\t\tlocalOpMetadata,\n\t\t);\n\n\t\tif (!handled) {\n\t\t\tthis.processMergeTreeMsg(message, local);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.didAttach}\n\t */\n\tprotected didAttach() {\n\t\t// If we are not local, and we've attached we need to start generating and sending ops\n\t\t// so start collaboration and provide a default client id incase we are not connected\n\t\tif (this.isAttached()) {\n\t\t\tthis.client.startOrUpdateCollaboration(this.runtime.clientId ?? \"attached\");\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.initializeLocalCore}\n\t */\n\tprotected initializeLocalCore() {\n\t\tsuper.initializeLocalCore();\n\t\tthis.initializeIntervalCollections();\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}\n\t */\n\tprotected applyStashedOp(content: any): void {\n\t\tif (!this.intervalCollections.tryApplyStashedOp(content)) {\n\t\t\tthis.client.applyStashedOp(content);\n\t\t}\n\t}\n\n\tprivate summarizeMergeTree(serializer: IFluidSerializer): ISummaryTreeWithStats {\n\t\tconst minSeq = this.deltaManager.minimumSequenceNumber;\n\n\t\tthis.processMinSequenceNumberChanged(minSeq);\n\n\t\tthis.messagesSinceMSNChange.forEach((m) => {\n\t\t\tm.minimumSequenceNumber = minSeq;\n\t\t});\n\n\t\treturn this.client.summarize(\n\t\t\tthis.runtime,\n\t\t\tthis.handle,\n\t\t\tserializer,\n\t\t\tthis.messagesSinceMSNChange,\n\t\t);\n\t}\n\n\t/**\n\t *\n\t * @param message - Message with decoded and hydrated handles\n\t */\n\tprivate processMergeTreeMsg(message: ISequencedDocumentMessage, local?: boolean) {\n\t\tconst ops: IMergeTreeDeltaOp[] = [];\n\t\tfunction transformOps(event: SequenceDeltaEvent) {\n\t\t\tops.push(...SharedSegmentSequence.createOpsFromDelta(event));\n\t\t}\n\t\tconst needsTransformation = message.referenceSequenceNumber !== message.sequenceNumber - 1;\n\t\tlet stashMessage: Readonly<ISequencedDocumentMessage> = message;\n\t\tif (this.runtime.options.newMergeTreeSnapshotFormat !== true) {\n\t\t\tif (needsTransformation) {\n\t\t\t\tthis.on(\"sequenceDelta\", transformOps);\n\t\t\t}\n\t\t}\n\n\t\tthis.client.applyMsg(message, local);\n\n\t\tif (this.runtime.options.newMergeTreeSnapshotFormat !== true) {\n\t\t\tif (needsTransformation) {\n\t\t\t\tthis.removeListener(\"sequenceDelta\", transformOps);\n\t\t\t\t// shallow clone the message as we only overwrite top level properties,\n\t\t\t\t// like referenceSequenceNumber and content only\n\t\t\t\tstashMessage = {\n\t\t\t\t\t...message,\n\t\t\t\t\treferenceSequenceNumber: stashMessage.sequenceNumber - 1,\n\t\t\t\t\t// eslint-disable-next-line import/no-deprecated\n\t\t\t\t\tcontents: ops.length !== 1 ? createGroupOp(...ops) : ops[0],\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis.messagesSinceMSNChange.push(stashMessage);\n\n\t\t\t// Do GC every once in a while...\n\t\t\tif (\n\t\t\t\tthis.messagesSinceMSNChange.length > 20 &&\n\t\t\t\tthis.messagesSinceMSNChange[20].sequenceNumber < message.minimumSequenceNumber\n\t\t\t) {\n\t\t\t\tthis.processMinSequenceNumberChanged(message.minimumSequenceNumber);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate processMinSequenceNumberChanged(minSeq: number) {\n\t\tlet index = 0;\n\t\tfor (; index < this.messagesSinceMSNChange.length; index++) {\n\t\t\tif (this.messagesSinceMSNChange[index].sequenceNumber > minSeq) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (index !== 0) {\n\t\t\tthis.messagesSinceMSNChange = this.messagesSinceMSNChange.slice(index);\n\t\t}\n\t}\n\n\tprivate initializeIntervalCollections() {\n\t\t// Listen and initialize new SharedIntervalCollections\n\t\tthis.intervalCollections.events.on(\n\t\t\t\"createIntervalCollection\",\n\t\t\t(key: string, local: boolean) => {\n\t\t\t\tconst intervalCollection = this.intervalCollections.get(key);\n\t\t\t\tif (!intervalCollection.attached) {\n\t\t\t\t\tintervalCollection.attachGraph(this.client, key);\n\t\t\t\t}\n\t\t\t\tthis.emit(\"createIntervalCollection\", key, local, this);\n\t\t\t},\n\t\t);\n\n\t\t// Initialize existing SharedIntervalCollections\n\t\tfor (const key of this.intervalCollections.keys()) {\n\t\t\tconst intervalCollection = this.intervalCollections.get(key);\n\t\t\tintervalCollection.attachGraph(this.client, key);\n\t\t}\n\t}\n\n\t/**\n\t * Overrides the \"currently applicable reference sequence number\" for the duration of the callback.\n\t * See remarks on `currentRefSeq` for more context.\n\t */\n\tprivate useResubmitRefSeq(refSeq: number, callback: () => void) {\n\t\tconst previousResubmitRefSeq = this.ongoingResubmitRefSeq;\n\t\tthis.ongoingResubmitRefSeq = refSeq;\n\t\ttry {\n\t\t\tcallback();\n\t\t} finally {\n\t\t\tthis.ongoingResubmitRefSeq = previousResubmitRefSeq;\n\t\t}\n\t}\n}\n\nfunction createReentrancyDetector(\n\tonReentrancy: (depth: number) => void,\n): <T>(callback: () => T) => T {\n\tlet depth = 0;\n\tfunction detectReentrancy<T>(callback: () => T): T {\n\t\tif (depth > 0) {\n\t\t\tonReentrancy(depth);\n\t\t}\n\t\tdepth++;\n\t\ttry {\n\t\t\treturn callback();\n\t\t} finally {\n\t\t\tdepth--;\n\t\t}\n\t}\n\n\treturn detectReentrancy;\n}\n\n/**\n * Apps which generate reentrant behavior may do so at a high frequency.\n * Logging even per-SharedSegmentSequence instance might be too noisy, and having a few logs from a session\n * is likely enough.\n */\nlet totalReentrancyLogs = 3;\n\n/**\n * Resets the reentrancy log counter. Test-only API.\n */\nexport function resetReentrancyLogCounter() {\n\ttotalReentrancyLogs = 3;\n}\n\nconst reentrancyErrorMessage = \"Reentrancy detected in sequence local ops\";\nconst ensureNoReentrancy = createReentrancyDetector(() => {\n\tthrow new LoggingError(reentrancyErrorMessage);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../src/sequence.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 { bufferToString } from \"@fluid-internal/client-utils\";\nimport { IEventThisPlaceHolder } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIChannelAttributes,\n\tIFluidDataStoreRuntime,\n\tIChannelStorageService,\n} from \"@fluidframework/datastore-definitions/internal\";\nimport {\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tClient,\n\tIJSONSegment,\n\tIMergeTreeAnnotateMsg,\n\tIMergeTreeDeltaOp,\n\t// eslint-disable-next-line import/no-deprecated\n\tIMergeTreeGroupMsg,\n\t// eslint-disable-next-line import/no-deprecated\n\tIMergeTreeObliterateMsg,\n\tIMergeTreeOp,\n\tIMergeTreeRemoveMsg,\n\tIRelativePosition,\n\tISegment,\n\tISegmentAction,\n\tLocalReferencePosition,\n\tMergeTreeDeltaType,\n\tMergeTreeRevertibleDriver,\n\tPropertySet,\n\tReferencePosition,\n\tReferenceType,\n\tSlidingPreference,\n\tcreateAnnotateRangeOp,\n\t// eslint-disable-next-line import/no-deprecated\n\tcreateGroupOp,\n\tcreateInsertOp,\n\tcreateObliterateRangeOp,\n\tcreateRemoveRangeOp,\n\tmatchProperties,\n\ttype AdjustParams,\n\ttype InteriorSequencePlace,\n\ttype MapLike,\n} from \"@fluidframework/merge-tree/internal\";\nimport {\n\tISummaryTreeWithStats,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\tObjectStoragePartition,\n\tSummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils/internal\";\nimport {\n\tIFluidSerializer,\n\tISharedObjectEvents,\n\tSharedObject,\n\ttype ISharedObject,\n} from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tLoggingError,\n\tcreateChildLogger,\n\tcreateConfigBasedOptionsProxy,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport Deque from \"double-ended-queue\";\n\nimport { type ISequenceIntervalCollection } from \"./intervalCollection.js\";\nimport { IMapOperation, IntervalCollectionMap } from \"./intervalCollectionMap.js\";\nimport {\n\tIMapMessageLocalMetadata,\n\ttype SequenceOptions,\n} from \"./intervalCollectionMapInterfaces.js\";\nimport {\n\tSequenceDeltaEvent,\n\tSequenceDeltaEventClass,\n\tSequenceMaintenanceEvent,\n\tSequenceMaintenanceEventClass,\n} from \"./sequenceDeltaEvent.js\";\n\nconst snapshotFileName = \"header\";\nconst contentPath = \"content\";\n\n/**\n * Events emitted in response to changes to the sequence data.\n *\n * @remarks\n *\n * The following is the list of events emitted.\n *\n * ### \"sequenceDelta\"\n *\n * The sequenceDelta event is emitted when segments are inserted, annotated, or removed.\n *\n * #### Listener signature\n *\n * ```typescript\n * (event: SequenceDeltaEvent, target: IEventThisPlaceHolder) => void\n * ```\n * - `event` - Various information on the segments that were modified.\n *\n * - `target` - The sequence itself.\n *\n * ### \"maintenance\"\n *\n * The maintenance event is emitted when segments are modified during merge-tree maintenance.\n *\n * #### Listener signature\n *\n * ```typescript\n * (event: SequenceMaintenanceEvent, target: IEventThisPlaceHolder) => void\n * ```\n * - `event` - Various information on the segments that were modified.\n *\n * - `target` - The sequence itself.\n * @legacy\n * @alpha\n */\nexport interface ISharedSegmentSequenceEvents extends ISharedObjectEvents {\n\t(\n\t\tevent: \"createIntervalCollection\",\n\t\tlistener: (label: string, local: boolean, target: IEventThisPlaceHolder) => void,\n\t): void;\n\t(\n\t\tevent: \"sequenceDelta\",\n\t\tlistener: (event: SequenceDeltaEvent, target: IEventThisPlaceHolder) => void,\n\t): void;\n\t(\n\t\tevent: \"maintenance\",\n\t\tlistener: (event: SequenceMaintenanceEvent, target: IEventThisPlaceHolder) => void,\n\t): void;\n}\n\n/**\n * @legacy\n * @alpha\n */\nexport interface ISharedSegmentSequence<T extends ISegment>\n\textends ISharedObject<ISharedSegmentSequenceEvents>,\n\t\tMergeTreeRevertibleDriver {\n\t/**\n\t * Creates a `LocalReferencePosition` on this SharedString. If the refType does not include\n\t * ReferenceType.Transient, the returned reference will be added to the localRefs on the provided segment.\n\t * @param segment - Segment to add the local reference on\n\t * @param offset - Offset on the segment at which to place the local reference\n\t * @param refType - ReferenceType for the created local reference\n\t * @param properties - PropertySet to place on the created local reference\n\t */\n\tcreateLocalReferencePosition(\n\t\tsegment: T,\n\t\toffset: number,\n\t\trefType: ReferenceType,\n\t\tproperties: PropertySet | undefined,\n\t\tslidingPreference?: SlidingPreference,\n\t\tcanSlideToEndpoint?: boolean,\n\t): LocalReferencePosition;\n\n\t/**\n\t * Removes a `LocalReferencePosition` from this SharedString.\n\t */\n\tremoveLocalReferencePosition(\n\t\tlref: LocalReferencePosition,\n\t): LocalReferencePosition | undefined;\n\n\t/**\n\t * Returns the length of the current sequence for the client\n\t */\n\tgetLength(): number;\n\n\t/**\n\t * Returns the current position of a segment, and -1 if the segment\n\t * does not exist in this sequence\n\t * @param segment - The segment to get the position of\n\t */\n\tgetPosition(segment: ISegment): number;\n\n\t/**\n\t * Resolves a `ReferencePosition` into a character position using this client's perspective.\n\t *\n\t * Reference positions that point to a character that has been removed will\n\t * always return the position of the nearest non-removed character, regardless\n\t * of `ReferenceType`. To handle this case specifically, one may wish\n\t * to look at the segment returned by `ReferencePosition.getSegment`.\n\t */\n\tlocalReferencePositionToPosition(lref: ReferencePosition): number;\n\n\t/**\n\t * Walk the underlying segments of the sequence.\n\t * The walked segments may extend beyond the range if the segments cross the\n\t * ranges start or end boundaries.\n\t *\n\t * Set split range to true to ensure only segments within the range are walked.\n\t *\n\t * @param handler - The function to handle each segment. Traversal ends if\n\t * this function returns true.\n\t * @param start - Optional. The start of range walk.\n\t * @param end - Optional. The end of range walk\n\t * @param accum - Optional. An object that will be passed to the handler for accumulation\n\t * @param splitRange - Optional. Splits boundary segments on the range boundaries. Defaults to false.\n\t */\n\twalkSegments<TClientData>(\n\t\thandler: ISegmentAction<TClientData>,\n\t\tstart?: number,\n\t\tend?: number,\n\t\taccum?: TClientData,\n\t\tsplitRange?: boolean,\n\t): void;\n\n\t/**\n\t * Inserts a segment directly before a `ReferencePosition`.\n\t * @param refPos - The reference position to insert the segment at\n\t * @param segment - The segment to insert\n\t */\n\tinsertAtReferencePosition(pos: ReferencePosition, segment: T): void;\n\n\t/**\n\t * Finds the segment information (i.e. segment + offset) corresponding to a character position in the SharedString.\n\t * If the position is past the end of the string, `segment` and `offset` on the returned object may be undefined.\n\t * @param pos - Character position (index) into the current local view of the SharedString.\n\t */\n\tgetContainingSegment(pos: number): {\n\t\tsegment: T | undefined;\n\t\toffset: number | undefined;\n\t};\n\n\tgetPropertiesAtPosition(pos: number): PropertySet | undefined;\n\n\t/**\n\t * @returns An iterable object that enumerates the IntervalCollection labels.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * const iter = this.getIntervalCollectionKeys();\n\t * for (key of iter)\n\t * const collection = this.getIntervalCollection(key);\n\t * ...\n\t * ```\n\t */\n\tgetIntervalCollectionLabels(): IterableIterator<string>;\n\n\t/**\n\t * Retrieves the interval collection keyed on `label`. If no such interval collection exists,\n\t * creates one.\n\t */\n\tgetIntervalCollection(label: string): ISequenceIntervalCollection;\n\n\t/**\n\t * Obliterate is similar to remove, but differs in that segments concurrently\n\t * inserted into an obliterated range will also be removed.\n\t * Inserts are considered concurrent to an obliterate iff the insert op's seq is after the obliterate op's refSeq\n\t * and the insert's refSeq is before the obliterates seq.\n\t * Inserts made by the client which most recently obliterated a range containing the insert position\n\t * are not considered concurrent to any obliteration (the last client to obliterate gets the right to insert).\n\t *\n\t * The endpoints can either be inclusive or exclusive.\n\t * Exclusive endpoints allow the obliterated range to \"grow\" to include adjacent concurrently inserted segments on that side.\n\t *\n\t * @param start - The start of the range to obliterate.\n\t * Inclusive if side is Before or a number is provided.\n\t * @param end - The end of the range to obliterate. Inclusive if side is After.\n\t * If a number is provided it is treated as exclusive,\n\t * but the endpoint does not expand in order to preserve existing behavior.\n\t *\n\t * @example Given the initial state `\"|ABC>\"`,\n\t * `obliterateRange({ pos: 0, side: Side.After }, { pos: 4, side: Side.Before })` obliterates `\"ABC\"`, leaving only `\"|>\"`.\n\t * `insertFromSpec(1, { text: \"AAA\"})` would insert `\"AAA\"` before |, resulting in `\"|AAA>\"`.\n\t * If another client does the same thing but inserts `\"BBB\"` and gets sequenced later, all clients will eventually see `|BBB>`.\n\t */\n\tobliterateRange(\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void;\n\n\t/**\n\t * @returns The most recent sequence number which has been acked by the server and processed by this\n\t * SharedSegmentSequence.\n\t */\n\tgetCurrentSeq(): number;\n\n\t/**\n\t * Annotates the range with the provided properties\n\t *\n\t * @param start - The inclusive start position of the range to annotate\n\t * @param end - The exclusive end position of the range to annotate\n\t * @param props - The properties to annotate the range with\n\t *\n\t */\n\tannotateRange(start: number, end: number, props: PropertySet): void;\n\n\t/**\n\t * Annotates a specified range within the sequence by applying the provided adjustments.\n\t *\n\t * @param start - The inclusive start position of the range to annotate. This is a zero-based index.\n\t * @param end - The exclusive end position of the range to annotate. This is a zero-based index.\n\t * @param adjust - A map-like object specifying the properties to adjust. Each key-value pair represents a property and its corresponding adjustment to be applied over the range.\n\t * An adjustment is defined by an object containing a `delta` to be added to the current property value, and optional `min` and `max` constraints to limit the adjusted value.\n\t *\n\t * @remarks\n\t * The range is defined by the start and end positions, where the start position is inclusive and the end position is exclusive.\n\t * The properties provided in the adjust parameter will be applied to the specified range. Each adjustment modifies the current value of the property by adding the specified `value`.\n\t * If the current value is not a number, the `delta` will be summed with 0 to compute the new value. The optional `min` and `max` constraints are applied after the adjustment to ensure the final value falls within the specified bounds.\n\t */\n\tannotateAdjustRange(start: number, end: number, adjust: MapLike<AdjustParams>): void;\n\n\t/**\n\t * @param start - The inclusive start of the range to remove\n\t * @param end - The exclusive end of the range to remove\n\t */\n\tremoveRange(start: number, end: number): void;\n\n\t/**\n\t * Resolves a remote client's position against the local sequence\n\t * and returns the remote client's position relative to the local\n\t * sequence. The client ref seq must be above the minimum sequence number\n\t * or the return value will be undefined.\n\t * Generally this method is used in conjunction with signals which provide\n\t * point in time values for the below parameters, and is useful for things\n\t * like displaying user position. It should not be used with persisted values\n\t * as persisted values will quickly become invalid as the remoteClientRefSeq\n\t * moves below the minimum sequence number\n\t * @param remoteClientPosition - The remote client's position to resolve\n\t * @param remoteClientRefSeq - The reference sequence number of the remote client\n\t * @param remoteClientId - The client id of the remote client\n\t */\n\tresolveRemoteClientPosition(\n\t\tremoteClientPosition: number,\n\t\tremoteClientRefSeq: number,\n\t\tremoteClientId: string,\n\t): number | undefined;\n\n\t// #region APIs we might want to remove\n\t/**\n\t * Initializes the object as a local, non-shared object. This object can become shared after\n\t * it is attached to the document.\n\t * @privateRemarks\n\t * TODO: determine if this API (from SharedObject) is needed by users of the encapsulated API, declarative API or both,\n\t * and handle exposing it in a consistent way for all SharedObjects if needed.\n\t */\n\tinitializeLocal(): void;\n\n\t/**\n\t * @deprecated The ability to create group ops will be removed in an upcoming\n\t * release, as group ops are redundant with the native batching capabilities\n\t * of the runtime\n\t */\n\t// eslint-disable-next-line import/no-deprecated\n\tgroupOperation(groupOp: IMergeTreeGroupMsg): void;\n\n\tgetRangeExtentsOfPosition(pos: number): {\n\t\tposStart: number | undefined;\n\t\tposAfterEnd: number | undefined;\n\t};\n\n\t/**\n\t * Inserts a segment\n\t * @param start - The position to insert the segment at\n\t * @param spec - The segment to inserts spec\n\t */\n\tinsertFromSpec(pos: number, spec: IJSONSegment): void;\n\n\t/**\n\t * Given a position specified relative to a marker id, lookup the marker\n\t * and convert the position to a character position.\n\t * @param relativePos - Id of marker (may be indirect) and whether position is before or after marker.\n\t */\n\tposFromRelativePos(relativePos: IRelativePosition): number;\n\n\t// #endregion\n}\n\n/**\n * @internal\n */\nexport abstract class SharedSegmentSequence<T extends ISegment>\n\textends SharedObject<ISharedSegmentSequenceEvents>\n\timplements ISharedSegmentSequence<T>\n{\n\t/**\n\t * This is a safeguard to avoid problematic reentrancy of local ops. This type of scenario occurs if the user of SharedString subscribes\n\t * to the `sequenceDelta` event and uses the callback for a local op to submit further local ops.\n\t * Historically (before 2.0.0-internal.6.1.0), doing so would result in eventual consistency issues or a corrupted document.\n\t * These issues were fixed in #16815 which makes such reentrancy no different from applying the ops in order but not from within the change events,\n\t * but there is still little test coverage for reentrant scenarios.\n\t * Additionally, applications submitting ops from inside change events need to take extreme care that their data models also support reentrancy.\n\t * Since this is likely not the case, by default SharedString throws when encountering reentrant ops.\n\t *\n\t * An application using SharedString which explicitly wants to opt in to allowing reentrancy anyway can set `sharedStringPreventReentrancy`\n\t * on the data store options to `false`.\n\t */\n\tprotected guardReentrancy: <TRet>(callback: () => TRet) => TRet;\n\n\tprivate static createOpsFromDelta(event: SequenceDeltaEvent): IMergeTreeDeltaOp[] {\n\t\tconst ops: IMergeTreeDeltaOp[] = [];\n\t\tfor (const r of event.ranges) {\n\t\t\tswitch (event.deltaOperation) {\n\t\t\t\tcase MergeTreeDeltaType.ANNOTATE: {\n\t\t\t\t\tconst lastAnnotate = ops[ops.length - 1] as IMergeTreeAnnotateMsg;\n\t\t\t\t\tconst props: PropertySet = {};\n\t\t\t\t\tfor (const key of Object.keys(r.propertyDeltas)) {\n\t\t\t\t\t\tprops[key] = r.segment.properties?.[key] ?? null;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tlastAnnotate &&\n\t\t\t\t\t\tlastAnnotate.pos2 === r.position &&\n\t\t\t\t\t\tmatchProperties(lastAnnotate.props, props)\n\t\t\t\t\t) {\n\t\t\t\t\t\tlastAnnotate.pos2 += r.segment.cachedLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tops.push(\n\t\t\t\t\t\t\tcreateAnnotateRangeOp(r.position, r.position + r.segment.cachedLength, props),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MergeTreeDeltaType.INSERT:\n\t\t\t\t\tops.push(createInsertOp(r.position, r.segment.clone().toJSONObject()));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MergeTreeDeltaType.REMOVE: {\n\t\t\t\t\tconst lastRem = ops[ops.length - 1] as IMergeTreeRemoveMsg;\n\t\t\t\t\tif (lastRem?.pos1 === r.position) {\n\t\t\t\t\t\tassert(lastRem.pos2 !== undefined, 0x3ff /* pos2 should not be undefined here */);\n\t\t\t\t\t\tlastRem.pos2 += r.segment.cachedLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tops.push(createRemoveRangeOp(r.position, r.position + r.segment.cachedLength));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MergeTreeDeltaType.OBLITERATE: {\n\t\t\t\t\t// eslint-disable-next-line import/no-deprecated\n\t\t\t\t\tconst lastRem = ops[ops.length - 1] as IMergeTreeObliterateMsg;\n\t\t\t\t\tif (lastRem?.pos1 === r.position) {\n\t\t\t\t\t\tassert(lastRem.pos2 !== undefined, 0x874 /* pos2 should not be undefined here */);\n\t\t\t\t\t\tlastRem.pos2 += r.segment.cachedLength;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tops.push(createObliterateRangeOp(r.position, r.position + r.segment.cachedLength));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t}\n\t\t}\n\t\treturn ops;\n\t}\n\n\t/**\n\t * Note: this field only provides a lower-bound on the reference sequence numbers for in-flight ops.\n\t * The exact reason isn't understood, but some e2e tests suggest that the runtime may sometimes process\n\t * incoming leave/join ops before putting an op that this DDS submits over the wire.\n\t *\n\t * E.g. SharedString submits an op while deltaManager has lastSequenceNumber = 10, but before the runtime\n\t * puts this op over the wire, it processes a client join/leave op with sequence number 11, so the referenceSequenceNumber\n\t * on the SharedString op is 11.\n\t *\n\t * The reference sequence numbers placed in this queue are also not accurate for stashed ops due to how the applyStashedOp\n\t * flow works at the runtime level. This is a legitimate bug, and AB#6602 tracks one way to fix it (stop reaching all the way\n\t * to deltaManager's lastSequenceNumber to obtain refSeq, instead leveraging some analogous notion on the container or datastore\n\t * runtime).\n\t */\n\tprivate readonly inFlightRefSeqs = new Deque<number>();\n\n\tprivate ongoingResubmitRefSeq: number | undefined;\n\n\t/**\n\t * Gets the reference sequence number (i.e. sequence number of the runtime's last processed op) for an op submitted\n\t * in the current context.\n\t *\n\t * This value can be optionally overridden using `useResubmitRefSeq`.\n\t * IntervalCollection's resubmit logic currently relies on preserving merge information from when the op was originally submitted,\n\t * even if the op is resubmitted more than once. Thus during resubmit, `inFlightRefSeqs` gets populated with the\n\t * original refSeq rather than the refSeq at the time of reconnection.\n\t *\n\t * @remarks - In some not fully understood cases, the runtime may process incoming ops before putting an op that this\n\t * DDS submits over the wire. See `inFlightRefSeqs` for more details.\n\t */\n\tprivate get currentRefSeq() {\n\t\treturn this.ongoingResubmitRefSeq ?? this.deltaManager.lastSequenceNumber;\n\t}\n\n\tprotected client: Client;\n\tprivate messagesSinceMSNChange: ISequencedDocumentMessage[] = [];\n\tprivate readonly intervalCollections: IntervalCollectionMap;\n\tconstructor(\n\t\tdataStoreRuntime: IFluidDataStoreRuntime,\n\t\tpublic id: string,\n\t\tattributes: IChannelAttributes,\n\t\tpublic readonly segmentFromSpec: (spec: IJSONSegment) => ISegment,\n\t) {\n\t\tsuper(id, dataStoreRuntime, attributes, \"fluid_sequence_\");\n\n\t\tconst getMinInFlightRefSeq = () => this.inFlightRefSeqs.get(0);\n\t\tthis.guardReentrancy =\n\t\t\t(dataStoreRuntime.options.sharedStringPreventReentrancy ?? true)\n\t\t\t\t? ensureNoReentrancy\n\t\t\t\t: createReentrancyDetector((depth) => {\n\t\t\t\t\t\tif (totalReentrancyLogs > 0) {\n\t\t\t\t\t\t\ttotalReentrancyLogs--;\n\t\t\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t\t\t{ eventName: \"LocalOpReentry\", depth },\n\t\t\t\t\t\t\t\tnew LoggingError(reentrancyErrorMessage),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\tconst options = createConfigBasedOptionsProxy<SequenceOptions>(\n\t\t\tloggerToMonitoringContext(this.logger).config,\n\t\t\t\"Fluid.Sequence\",\n\t\t\t{\n\t\t\t\tmergeTreeEnableObliterate: (c, n) => c.getBoolean(n),\n\t\t\t\tmergeTreeEnableSidedObliterate: (c, n) => c.getBoolean(n),\n\t\t\t\tintervalStickinessEnabled: (c, n) => c.getBoolean(n),\n\t\t\t\tmergeTreeReferencesCanSlideToEndpoint: (c, n) => c.getBoolean(n),\n\t\t\t\tmergeTreeEnableAnnotateAdjust: (c, n) => c.getBoolean(n),\n\t\t\t},\n\t\t\tdataStoreRuntime.options,\n\t\t);\n\n\t\tthis.client = new Client(\n\t\t\tsegmentFromSpec,\n\t\t\tcreateChildLogger({\n\t\t\t\tlogger: this.logger,\n\t\t\t\tnamespace: \"SharedSegmentSequence.MergeTreeClient\",\n\t\t\t}),\n\t\t\toptions,\n\t\t\tgetMinInFlightRefSeq,\n\t\t);\n\n\t\tthis.client.prependListener(\"delta\", (opArgs, deltaArgs) => {\n\t\t\tconst event = new SequenceDeltaEventClass(opArgs, deltaArgs, this.client);\n\t\t\tif (event.isLocal && event.opArgs.rollback !== true) {\n\t\t\t\tthis.submitSequenceMessage(opArgs.op);\n\t\t\t}\n\t\t\tif (deltaArgs.deltaSegments.length > 0) {\n\t\t\t\tthis.emit(\"sequenceDelta\", event, this);\n\t\t\t}\n\t\t});\n\n\t\tthis.client.on(\"maintenance\", (args, opArgs) => {\n\t\t\tthis.emit(\n\t\t\t\t\"maintenance\",\n\t\t\t\tnew SequenceMaintenanceEventClass(opArgs, args, this.client),\n\t\t\t\tthis,\n\t\t\t);\n\t\t});\n\n\t\tthis.intervalCollections = new IntervalCollectionMap(\n\t\t\tthis.serializer,\n\t\t\tthis.handle,\n\t\t\t(op, localOpMetadata) => {\n\t\t\t\tif (!this.isAttached()) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.inFlightRefSeqs.push(this.currentRefSeq);\n\t\t\t\tthis.submitLocalMessage(op, localOpMetadata);\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\tpublic removeRange(start: number, end: number): void {\n\t\tthis.guardReentrancy(() => this.client.removeRangeLocal(start, end));\n\t}\n\n\tpublic obliterateRange(\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tthis.guardReentrancy(() => this.client.obliterateRangeLocal(start, end));\n\t}\n\n\t// eslint-disable-next-line import/no-deprecated\n\tpublic groupOperation(groupOp: IMergeTreeGroupMsg): void {\n\t\tthis.guardReentrancy(() => this.client.localTransaction(groupOp));\n\t}\n\n\tpublic getContainingSegment(pos: number): {\n\t\tsegment: T | undefined;\n\t\toffset: number | undefined;\n\t} {\n\t\treturn this.client.getContainingSegment<T>(pos);\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this.client.getLength();\n\t}\n\n\tpublic getPosition(segment: ISegment): number {\n\t\treturn this.client.getPosition(segment);\n\t}\n\n\tpublic annotateRange(start: number, end: number, props: PropertySet): void {\n\t\tthis.guardReentrancy(() => this.client.annotateRangeLocal(start, end, props));\n\t}\n\n\tpublic annotateAdjustRange(start: number, end: number, adjust: MapLike<AdjustParams>): void {\n\t\tthis.guardReentrancy(() => this.client.annotateAdjustRangeLocal(start, end, adjust));\n\t}\n\n\tpublic getPropertiesAtPosition(pos: number): PropertySet | undefined {\n\t\treturn this.client.getPropertiesAtPosition(pos);\n\t}\n\n\tpublic getRangeExtentsOfPosition(pos: number): {\n\t\tposStart: number | undefined;\n\t\tposAfterEnd: number | undefined;\n\t} {\n\t\treturn this.client.getRangeExtentsOfPosition(pos);\n\t}\n\n\tpublic createLocalReferencePosition(\n\t\tsegment: T,\n\t\toffset: number,\n\t\trefType: ReferenceType,\n\t\tproperties: PropertySet | undefined,\n\t\tslidingPreference?: SlidingPreference,\n\t\tcanSlideToEndpoint?: boolean,\n\t): LocalReferencePosition {\n\t\treturn this.client.createLocalReferencePosition(\n\t\t\tsegment,\n\t\t\toffset,\n\t\t\trefType,\n\t\t\tproperties,\n\t\t\tslidingPreference,\n\t\t\tcanSlideToEndpoint,\n\t\t);\n\t}\n\n\tpublic localReferencePositionToPosition(lref: ReferencePosition): number {\n\t\treturn this.client.localReferencePositionToPosition(lref);\n\t}\n\n\tpublic removeLocalReferencePosition(\n\t\tlref: LocalReferencePosition,\n\t): LocalReferencePosition | undefined {\n\t\treturn this.client.removeLocalReferencePosition(lref);\n\t}\n\n\tpublic resolveRemoteClientPosition(\n\t\tremoteClientPosition: number,\n\t\tremoteClientRefSeq: number,\n\t\tremoteClientId: string,\n\t): number | undefined {\n\t\treturn this.client.resolveRemoteClientPosition(\n\t\t\tremoteClientPosition,\n\t\t\tremoteClientRefSeq,\n\t\t\tremoteClientId,\n\t\t);\n\t}\n\n\tprivate submitSequenceMessage(message: IMergeTreeOp) {\n\t\tif (!this.isAttached()) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.inFlightRefSeqs.push(this.currentRefSeq);\n\n\t\tconst metadata = this.client.peekPendingSegmentGroups(\n\t\t\tmessage.type === MergeTreeDeltaType.GROUP ? message.ops.length : 1,\n\t\t);\n\n\t\tthis.submitLocalMessage(message, metadata);\n\t}\n\n\tpublic posFromRelativePos(relativePos: IRelativePosition): number {\n\t\treturn this.client.posFromRelativePos(relativePos);\n\t}\n\n\tpublic walkSegments<TClientData>(\n\t\thandler: ISegmentAction<TClientData>,\n\t\tstart?: number,\n\t\tend?: number,\n\t\taccum?: TClientData,\n\t\tsplitRange: boolean = false,\n\t): void {\n\t\tthis.client.walkSegments(handler, start, end, accum as TClientData, splitRange);\n\t}\n\n\tpublic getCurrentSeq(): number {\n\t\treturn this.client.getCurrentSeq();\n\t}\n\n\tpublic insertAtReferencePosition(pos: ReferencePosition, segment: T): void {\n\t\tthis.guardReentrancy(() => this.client.insertAtReferencePositionLocal(pos, segment));\n\t}\n\n\tpublic insertFromSpec(pos: number, spec: IJSONSegment): void {\n\t\tconst segment = this.segmentFromSpec(spec);\n\t\tthis.guardReentrancy(() => this.client.insertSegmentLocal(pos, segment));\n\t}\n\n\tpublic getIntervalCollection(label: string): ISequenceIntervalCollection {\n\t\treturn this.intervalCollections.get(label);\n\t}\n\n\tpublic getIntervalCollectionLabels(): IterableIterator<string> {\n\t\treturn this.intervalCollections.keys();\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.summarizeCore}\n\t */\n\tprotected summarizeCore(\n\t\tserializer: IFluidSerializer,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): ISummaryTreeWithStats {\n\t\tconst builder = new SummaryTreeBuilder();\n\n\t\t// conditionally write the interval collection blob\n\t\t// only if it has entries\n\t\tif (this.intervalCollections.size > 0) {\n\t\t\tbuilder.addBlob(snapshotFileName, this.intervalCollections.serialize(serializer));\n\t\t}\n\n\t\tbuilder.addWithStats(contentPath, this.summarizeMergeTree(serializer));\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\t/**\n\t * Runs serializer over the GC data for this SharedMatrix.\n\t * All the IFluidHandle's represent routes to other objects.\n\t */\n\tprotected processGCDataCore(serializer: IFluidSerializer) {\n\t\tif (this.intervalCollections.size > 0) {\n\t\t\tthis.intervalCollections.serialize(serializer);\n\t\t}\n\n\t\tthis.client.serializeGCData(this.handle, serializer);\n\t}\n\n\t/**\n\t * Replace the range specified from start to end with the provided segment\n\t * This is done by inserting the segment at the end of the range, followed\n\t * by removing the contents of the range\n\t * For a zero or reverse range (start \\>= end), insert at end do not remove anything\n\t * @param start - The start of the range to replace\n\t * @param end - The end of the range to replace\n\t * @param segment - The segment that will replace the range\n\t */\n\tprotected replaceRange(start: number, end: number, segment: ISegment): void {\n\t\t// Insert at the max end of the range when start > end, but still remove the range later\n\t\tconst insertIndex: number = Math.max(start, end);\n\n\t\t// Insert first, so local references can slide to the inserted seg if any\n\t\tconst insert = this.guardReentrancy(() =>\n\t\t\tthis.client.insertSegmentLocal(insertIndex, segment),\n\t\t);\n\n\t\tif (insert && start < end) {\n\t\t\tthis.removeRange(start, end);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.onConnect}\n\t */\n\tprotected onConnect() {\n\t\t// Update merge tree collaboration information with new client ID and then resend pending ops\n\t\tthis.client.startOrUpdateCollaboration(this.runtime.clientId);\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.onDisconnect}\n\t */\n\tprotected onDisconnect() {}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.reSubmitCore}\n\t */\n\tprotected reSubmitCore(content: any, localOpMetadata: unknown, squash: boolean = false) {\n\t\tconst originalRefSeq = this.inFlightRefSeqs.shift();\n\t\tassert(\n\t\t\toriginalRefSeq !== undefined,\n\t\t\t0x8bb /* Expected a recorded refSeq when resubmitting an op */,\n\t\t);\n\t\tthis.useResubmitRefSeq(originalRefSeq, () => {\n\t\t\tif (\n\t\t\t\t!this.intervalCollections.tryResubmitMessage(\n\t\t\t\t\tcontent,\n\t\t\t\t\tlocalOpMetadata as IMapMessageLocalMetadata,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthis.submitSequenceMessage(\n\t\t\t\t\tthis.client.regeneratePendingOp(content as IMergeTreeOp, localOpMetadata, squash),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected reSubmitSquashed(content: unknown, localOpMetadata: unknown): void {\n\t\tthis.reSubmitCore(content, localOpMetadata, true);\n\t}\n\n\t/**\n\t * Revert an op\n\t */\n\tprotected rollback(content: any, localOpMetadata: unknown): void {\n\t\tconst originalRefSeq = this.inFlightRefSeqs.pop();\n\t\tassert(\n\t\t\toriginalRefSeq !== undefined,\n\t\t\t0xb7f /* Expected a recorded refSeq when rolling back an op */,\n\t\t);\n\n\t\tif (!this.intervalCollections.tryRollback(content, localOpMetadata)) {\n\t\t\tthis.client.rollback(content, localOpMetadata);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}\n\t */\n\tprotected async loadCore(storage: IChannelStorageService) {\n\t\tif (await storage.contains(snapshotFileName)) {\n\t\t\tconst blob = await storage.readBlob(snapshotFileName);\n\t\t\tconst header = bufferToString(blob, \"utf8\");\n\t\t\tthis.intervalCollections.populate(header);\n\t\t}\n\n\t\ttry {\n\t\t\t// this will load the header, and return a promise\n\t\t\t// that will resolve when the body is loaded\n\t\t\t// and the catchup ops are available.\n\t\t\tconst { catchupOpsP } = await this.client.load(\n\t\t\t\tthis.runtime,\n\t\t\t\tnew ObjectStoragePartition(storage, contentPath),\n\t\t\t\tthis.serializer,\n\t\t\t);\n\n\t\t\t// process the catch up ops, and finishing the loading process\n\t\t\t(await catchupOpsP).forEach((m) => {\n\t\t\t\tconst collabWindow = this.client.getCollabWindow();\n\t\t\t\tif (\n\t\t\t\t\tm.minimumSequenceNumber < collabWindow.minSeq ||\n\t\t\t\t\tm.referenceSequenceNumber < collabWindow.minSeq ||\n\t\t\t\t\tm.sequenceNumber <= collabWindow.minSeq ||\n\t\t\t\t\t// sequenceNumber could be the same if messages are part of a grouped batch\n\t\t\t\t\tm.sequenceNumber < collabWindow.currentSeq\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid catchup operations in snapshot: ${JSON.stringify({\n\t\t\t\t\t\t\top: {\n\t\t\t\t\t\t\t\tseq: m.sequenceNumber,\n\t\t\t\t\t\t\t\tminSeq: m.minimumSequenceNumber,\n\t\t\t\t\t\t\t\trefSeq: m.referenceSequenceNumber,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcollabWindow: {\n\t\t\t\t\t\t\t\tseq: collabWindow.currentSeq,\n\t\t\t\t\t\t\t\tminSeq: collabWindow.minSeq,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.processMergeTreeMsg(m);\n\t\t\t});\n\n\t\t\t// Initialize the interval collections\n\t\t\tthis.initializeIntervalCollections();\n\t\t} catch (error) {\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"SequenceLoadFailed\" }, error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.processCore}\n\t */\n\tprotected processCore(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t) {\n\t\tif (local) {\n\t\t\tconst recordedRefSeq = this.inFlightRefSeqs.shift();\n\t\t\tassert(recordedRefSeq !== undefined, 0x8bc /* No pending recorded refSeq found */);\n\t\t\t// TODO: AB#7076: Some equivalent assert should be enabled. This fails some e2e stashed op tests because\n\t\t\t// the deltaManager may have seen more messages than the runtime has processed while amidst the stashed op\n\t\t\t// flow, so e.g. when `applyStashedOp` is called and the DDS is put in a state where it expects an ack for\n\t\t\t// one of its messages, the delta manager has actually already seen subsequent messages from collaborators\n\t\t\t// which the in-flight message is concurrent to.\n\t\t\t// See \"handles stashed ops created on top of sequenced local ops\" for one such test case.\n\t\t\t// assert(recordedRefSeq <= message.referenceSequenceNumber, \"RefSeq mismatch\");\n\t\t}\n\n\t\tassert(\n\t\t\tmessage.type === MessageType.Operation,\n\t\t\t0x073 /* \"Sequence message not operation\" */,\n\t\t);\n\n\t\tconst handled = this.intervalCollections.tryProcessMessage(\n\t\t\tmessage.contents as IMapOperation,\n\t\t\tlocal,\n\t\t\tmessage,\n\t\t\tlocalOpMetadata,\n\t\t);\n\n\t\tif (!handled) {\n\t\t\tthis.processMergeTreeMsg(message, local);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.didAttach}\n\t */\n\tprotected didAttach() {\n\t\t// If we are not local, and we've attached we need to start generating and sending ops\n\t\t// so start collaboration and provide a default client id incase we are not connected\n\t\tif (this.isAttached()) {\n\t\t\tthis.client.startOrUpdateCollaboration(this.runtime.clientId ?? \"attached\");\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.initializeLocalCore}\n\t */\n\tprotected initializeLocalCore() {\n\t\tsuper.initializeLocalCore();\n\t\tthis.initializeIntervalCollections();\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}\n\t */\n\tprotected applyStashedOp(content: any): void {\n\t\tif (!this.intervalCollections.tryApplyStashedOp(content)) {\n\t\t\tthis.client.applyStashedOp(content);\n\t\t}\n\t}\n\n\tprivate summarizeMergeTree(serializer: IFluidSerializer): ISummaryTreeWithStats {\n\t\tconst minSeq = this.deltaManager.minimumSequenceNumber;\n\n\t\tthis.processMinSequenceNumberChanged(minSeq);\n\n\t\tthis.messagesSinceMSNChange.forEach((m) => {\n\t\t\tm.minimumSequenceNumber = minSeq;\n\t\t});\n\n\t\treturn this.client.summarize(\n\t\t\tthis.runtime,\n\t\t\tthis.handle,\n\t\t\tserializer,\n\t\t\tthis.messagesSinceMSNChange,\n\t\t);\n\t}\n\n\t/**\n\t *\n\t * @param message - Message with decoded and hydrated handles\n\t */\n\tprivate processMergeTreeMsg(message: ISequencedDocumentMessage, local?: boolean) {\n\t\tconst ops: IMergeTreeDeltaOp[] = [];\n\t\tfunction transformOps(event: SequenceDeltaEvent) {\n\t\t\tops.push(...SharedSegmentSequence.createOpsFromDelta(event));\n\t\t}\n\t\tconst needsTransformation = message.referenceSequenceNumber !== message.sequenceNumber - 1;\n\t\tlet stashMessage: Readonly<ISequencedDocumentMessage> = message;\n\t\tif (this.runtime.options.newMergeTreeSnapshotFormat !== true) {\n\t\t\tif (needsTransformation) {\n\t\t\t\tthis.on(\"sequenceDelta\", transformOps);\n\t\t\t}\n\t\t}\n\n\t\tthis.client.applyMsg(message, local);\n\n\t\tif (this.runtime.options.newMergeTreeSnapshotFormat !== true) {\n\t\t\tif (needsTransformation) {\n\t\t\t\tthis.removeListener(\"sequenceDelta\", transformOps);\n\t\t\t\t// shallow clone the message as we only overwrite top level properties,\n\t\t\t\t// like referenceSequenceNumber and content only\n\t\t\t\tstashMessage = {\n\t\t\t\t\t...message,\n\t\t\t\t\treferenceSequenceNumber: stashMessage.sequenceNumber - 1,\n\t\t\t\t\t// eslint-disable-next-line import/no-deprecated\n\t\t\t\t\tcontents: ops.length !== 1 ? createGroupOp(...ops) : ops[0],\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis.messagesSinceMSNChange.push(stashMessage);\n\n\t\t\t// Do GC every once in a while...\n\t\t\tif (\n\t\t\t\tthis.messagesSinceMSNChange.length > 20 &&\n\t\t\t\tthis.messagesSinceMSNChange[20].sequenceNumber < message.minimumSequenceNumber\n\t\t\t) {\n\t\t\t\tthis.processMinSequenceNumberChanged(message.minimumSequenceNumber);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate processMinSequenceNumberChanged(minSeq: number) {\n\t\tlet index = 0;\n\t\tfor (; index < this.messagesSinceMSNChange.length; index++) {\n\t\t\tif (this.messagesSinceMSNChange[index].sequenceNumber > minSeq) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (index !== 0) {\n\t\t\tthis.messagesSinceMSNChange = this.messagesSinceMSNChange.slice(index);\n\t\t}\n\t}\n\n\tprivate initializeIntervalCollections() {\n\t\t// Listen and initialize new SharedIntervalCollections\n\t\tthis.intervalCollections.events.on(\n\t\t\t\"createIntervalCollection\",\n\t\t\t(key: string, local: boolean) => {\n\t\t\t\tconst intervalCollection = this.intervalCollections.get(key);\n\t\t\t\tif (!intervalCollection.attached) {\n\t\t\t\t\tintervalCollection.attachGraph(this.client, key);\n\t\t\t\t}\n\t\t\t\tthis.emit(\"createIntervalCollection\", key, local, this);\n\t\t\t},\n\t\t);\n\n\t\t// Initialize existing SharedIntervalCollections\n\t\tfor (const key of this.intervalCollections.keys()) {\n\t\t\tconst intervalCollection = this.intervalCollections.get(key);\n\t\t\tintervalCollection.attachGraph(this.client, key);\n\t\t}\n\t}\n\n\t/**\n\t * Overrides the \"currently applicable reference sequence number\" for the duration of the callback.\n\t * See remarks on `currentRefSeq` for more context.\n\t */\n\tprivate useResubmitRefSeq(refSeq: number, callback: () => void) {\n\t\tconst previousResubmitRefSeq = this.ongoingResubmitRefSeq;\n\t\tthis.ongoingResubmitRefSeq = refSeq;\n\t\ttry {\n\t\t\tcallback();\n\t\t} finally {\n\t\t\tthis.ongoingResubmitRefSeq = previousResubmitRefSeq;\n\t\t}\n\t}\n}\n\nfunction createReentrancyDetector(\n\tonReentrancy: (depth: number) => void,\n): <T>(callback: () => T) => T {\n\tlet depth = 0;\n\tfunction detectReentrancy<T>(callback: () => T): T {\n\t\tif (depth > 0) {\n\t\t\tonReentrancy(depth);\n\t\t}\n\t\tdepth++;\n\t\ttry {\n\t\t\treturn callback();\n\t\t} finally {\n\t\t\tdepth--;\n\t\t}\n\t}\n\n\treturn detectReentrancy;\n}\n\n/**\n * Apps which generate reentrant behavior may do so at a high frequency.\n * Logging even per-SharedSegmentSequence instance might be too noisy, and having a few logs from a session\n * is likely enough.\n */\nlet totalReentrancyLogs = 3;\n\n/**\n * Resets the reentrancy log counter. Test-only API.\n */\nexport function resetReentrancyLogCounter() {\n\ttotalReentrancyLogs = 3;\n}\n\nconst reentrancyErrorMessage = \"Reentrancy detected in sequence local ops\";\nconst ensureNoReentrancy = createReentrancyDetector(() => {\n\tthrow new LoggingError(reentrancyErrorMessage);\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/sequence",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.42.0",
|
|
4
4
|
"description": "Distributed sequence",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -91,33 +91,33 @@
|
|
|
91
91
|
"temp-directory": "nyc/.nyc_output"
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@fluid-internal/client-utils": "2.
|
|
95
|
-
"@fluidframework/core-interfaces": "2.
|
|
96
|
-
"@fluidframework/core-utils": "2.
|
|
97
|
-
"@fluidframework/datastore-definitions": "2.
|
|
98
|
-
"@fluidframework/driver-definitions": "2.
|
|
99
|
-
"@fluidframework/merge-tree": "2.
|
|
100
|
-
"@fluidframework/runtime-definitions": "2.
|
|
101
|
-
"@fluidframework/runtime-utils": "2.
|
|
102
|
-
"@fluidframework/shared-object-base": "2.
|
|
103
|
-
"@fluidframework/telemetry-utils": "2.
|
|
94
|
+
"@fluid-internal/client-utils": "~2.42.0",
|
|
95
|
+
"@fluidframework/core-interfaces": "~2.42.0",
|
|
96
|
+
"@fluidframework/core-utils": "~2.42.0",
|
|
97
|
+
"@fluidframework/datastore-definitions": "~2.42.0",
|
|
98
|
+
"@fluidframework/driver-definitions": "~2.42.0",
|
|
99
|
+
"@fluidframework/merge-tree": "~2.42.0",
|
|
100
|
+
"@fluidframework/runtime-definitions": "~2.42.0",
|
|
101
|
+
"@fluidframework/runtime-utils": "~2.42.0",
|
|
102
|
+
"@fluidframework/shared-object-base": "~2.42.0",
|
|
103
|
+
"@fluidframework/telemetry-utils": "~2.42.0",
|
|
104
104
|
"double-ended-queue": "^2.1.0-0",
|
|
105
105
|
"uuid": "^9.0.0"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
108
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
109
109
|
"@biomejs/biome": "~1.9.3",
|
|
110
|
-
"@fluid-internal/mocha-test-setup": "2.
|
|
111
|
-
"@fluid-private/stochastic-test-utils": "2.
|
|
112
|
-
"@fluid-private/test-dds-utils": "2.
|
|
110
|
+
"@fluid-internal/mocha-test-setup": "~2.42.0",
|
|
111
|
+
"@fluid-private/stochastic-test-utils": "~2.42.0",
|
|
112
|
+
"@fluid-private/test-dds-utils": "~2.42.0",
|
|
113
113
|
"@fluid-tools/benchmark": "^0.51.0",
|
|
114
114
|
"@fluid-tools/build-cli": "^0.55.0",
|
|
115
115
|
"@fluidframework/build-common": "^2.0.3",
|
|
116
116
|
"@fluidframework/build-tools": "^0.55.0",
|
|
117
|
-
"@fluidframework/container-definitions": "2.
|
|
118
|
-
"@fluidframework/eslint-config-fluid": "^5.7.
|
|
119
|
-
"@fluidframework/sequence-previous": "npm:@fluidframework/sequence@2.
|
|
120
|
-
"@fluidframework/test-runtime-utils": "2.
|
|
117
|
+
"@fluidframework/container-definitions": "~2.42.0",
|
|
118
|
+
"@fluidframework/eslint-config-fluid": "^5.7.4",
|
|
119
|
+
"@fluidframework/sequence-previous": "npm:@fluidframework/sequence@2.41.0",
|
|
120
|
+
"@fluidframework/test-runtime-utils": "~2.42.0",
|
|
121
121
|
"@microsoft/api-extractor": "7.52.8",
|
|
122
122
|
"@types/diff": "^3.5.1",
|
|
123
123
|
"@types/double-ended-queue": "^2.1.0",
|
|
@@ -705,11 +705,7 @@ export class IntervalCollection
|
|
|
705
705
|
number,
|
|
706
706
|
ISerializedInterval | SerializedIntervalDelta
|
|
707
707
|
>();
|
|
708
|
-
private readonly
|
|
709
|
-
string,
|
|
710
|
-
ISerializedIntervalCollectionV1
|
|
711
|
-
>();
|
|
712
|
-
private readonly pendingChangesEnd: Map<string, ISerializedIntervalCollectionV1> = new Map<
|
|
708
|
+
private readonly pendingChanges: Map<string, ISerializedIntervalCollectionV1> = new Map<
|
|
713
709
|
string,
|
|
714
710
|
ISerializedIntervalCollectionV1
|
|
715
711
|
>();
|
|
@@ -854,9 +850,8 @@ export class IntervalCollection
|
|
|
854
850
|
localOpMetadata: IMapMessageLocalMetadata,
|
|
855
851
|
): void {
|
|
856
852
|
const { opName, value } = op;
|
|
857
|
-
const { localSeq } = localOpMetadata;
|
|
858
853
|
const rebasedValue =
|
|
859
|
-
opName === "delete" ? value : this.rebaseLocalInterval(opName, value,
|
|
854
|
+
opName === "delete" ? value : this.rebaseLocalInterval(opName, value, localOpMetadata);
|
|
860
855
|
if (rebasedValue === undefined) {
|
|
861
856
|
return undefined;
|
|
862
857
|
}
|
|
@@ -1110,8 +1105,10 @@ export class IntervalCollection
|
|
|
1110
1105
|
|
|
1111
1106
|
this.assertStickinessEnabled(start, end);
|
|
1112
1107
|
|
|
1108
|
+
const intervalId = id ?? uuid();
|
|
1109
|
+
|
|
1113
1110
|
const interval: SequenceIntervalClass = this.localCollection.addInterval(
|
|
1114
|
-
|
|
1111
|
+
intervalId,
|
|
1115
1112
|
toSequencePlace(startPos, startSide),
|
|
1116
1113
|
toSequencePlace(endPos, endSide),
|
|
1117
1114
|
props,
|
|
@@ -1136,6 +1133,7 @@ export class IntervalCollection
|
|
|
1136
1133
|
},
|
|
1137
1134
|
{
|
|
1138
1135
|
localSeq,
|
|
1136
|
+
intervalId,
|
|
1139
1137
|
},
|
|
1140
1138
|
);
|
|
1141
1139
|
}
|
|
@@ -1174,6 +1172,7 @@ export class IntervalCollection
|
|
|
1174
1172
|
{
|
|
1175
1173
|
localSeq: this.getNextLocalSeq(),
|
|
1176
1174
|
previous: interval.serialize(),
|
|
1175
|
+
intervalId: interval.getIntervalId(),
|
|
1177
1176
|
},
|
|
1178
1177
|
);
|
|
1179
1178
|
} else {
|
|
@@ -1269,6 +1268,7 @@ export class IntervalCollection
|
|
|
1269
1268
|
{
|
|
1270
1269
|
localSeq,
|
|
1271
1270
|
previous: interval.serialize(),
|
|
1271
|
+
intervalId: id,
|
|
1272
1272
|
},
|
|
1273
1273
|
);
|
|
1274
1274
|
}
|
|
@@ -1302,65 +1302,39 @@ export class IntervalCollection
|
|
|
1302
1302
|
if (!this.isCollaborating) {
|
|
1303
1303
|
return;
|
|
1304
1304
|
}
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
private addPendingChangeHelper(
|
|
1314
|
-
id: string,
|
|
1315
|
-
pendingChanges: Map<string, SerializedIntervalDelta[]>,
|
|
1316
|
-
serializedInterval: SerializedIntervalDelta,
|
|
1317
|
-
) {
|
|
1318
|
-
let entries: SerializedIntervalDelta[] | undefined = pendingChanges.get(id);
|
|
1319
|
-
if (!entries) {
|
|
1320
|
-
entries = [];
|
|
1321
|
-
pendingChanges.set(id, entries);
|
|
1305
|
+
assert(
|
|
1306
|
+
(serializedInterval.start === undefined) === (serializedInterval.end === undefined),
|
|
1307
|
+
0xbb0 /* both start and end must be set or unset */,
|
|
1308
|
+
);
|
|
1309
|
+
if (serializedInterval.start !== undefined || serializedInterval.end !== undefined) {
|
|
1310
|
+
const entries = this.pendingChanges.get(id) ?? [];
|
|
1311
|
+
this.pendingChanges.set(id, entries);
|
|
1312
|
+
entries.push(serializedInterval as any);
|
|
1322
1313
|
}
|
|
1323
|
-
entries.push(serializedInterval);
|
|
1324
1314
|
}
|
|
1325
1315
|
|
|
1326
1316
|
private removePendingChange(serializedInterval: SerializedIntervalDelta) {
|
|
1327
1317
|
// Change ops always have an ID.
|
|
1328
1318
|
const { id } = getSerializedProperties(serializedInterval);
|
|
1329
1319
|
if (serializedInterval.start !== undefined) {
|
|
1330
|
-
this.
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
const entries = pendingChanges.get(id);
|
|
1343
|
-
if (entries) {
|
|
1344
|
-
const pendingChange = entries.shift();
|
|
1345
|
-
if (entries.length === 0) {
|
|
1346
|
-
pendingChanges.delete(id);
|
|
1347
|
-
}
|
|
1348
|
-
if (
|
|
1349
|
-
pendingChange?.start !== serializedInterval.start ||
|
|
1350
|
-
pendingChange?.end !== serializedInterval.end
|
|
1351
|
-
) {
|
|
1352
|
-
throw new LoggingError("Mismatch in pending changes");
|
|
1320
|
+
const entries = this.pendingChanges.get(id);
|
|
1321
|
+
if (entries) {
|
|
1322
|
+
const pendingChange = entries.shift();
|
|
1323
|
+
if (entries.length === 0) {
|
|
1324
|
+
this.pendingChanges.delete(id);
|
|
1325
|
+
}
|
|
1326
|
+
if (
|
|
1327
|
+
pendingChange?.start !== serializedInterval.start ||
|
|
1328
|
+
pendingChange?.end !== serializedInterval.end
|
|
1329
|
+
) {
|
|
1330
|
+
throw new LoggingError("Mismatch in pending changes");
|
|
1331
|
+
}
|
|
1353
1332
|
}
|
|
1354
1333
|
}
|
|
1355
1334
|
}
|
|
1356
1335
|
|
|
1357
|
-
private
|
|
1358
|
-
const entries = this.
|
|
1359
|
-
return entries && entries.length !== 0;
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
private hasPendingChangeEnd(id: string) {
|
|
1363
|
-
const entries = this.pendingChangesEnd.get(id);
|
|
1336
|
+
private hasPendingChanges(id: string) {
|
|
1337
|
+
const entries = this.pendingChanges.get(id);
|
|
1364
1338
|
return entries && entries.length !== 0;
|
|
1365
1339
|
}
|
|
1366
1340
|
|
|
@@ -1374,22 +1348,23 @@ export class IntervalCollection
|
|
|
1374
1348
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
1375
1349
|
}
|
|
1376
1350
|
|
|
1351
|
+
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
1352
|
+
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
1353
|
+
// strip it out of the properties here.
|
|
1354
|
+
const { id, properties } = getSerializedProperties(serializedInterval);
|
|
1355
|
+
assert(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1356
|
+
const interval: SequenceIntervalClass | undefined = this.getIntervalById(id);
|
|
1357
|
+
|
|
1377
1358
|
if (local) {
|
|
1378
1359
|
assert(
|
|
1379
1360
|
localOpMetadata !== undefined,
|
|
1380
1361
|
0x552 /* op metadata should be defined for local op */,
|
|
1381
1362
|
);
|
|
1382
|
-
this.localSeqToSerializedInterval.delete(localOpMetadata?.localSeq);
|
|
1383
1363
|
// This is an ack from the server. Remove the pending change.
|
|
1364
|
+
this.localSeqToSerializedInterval.delete(localOpMetadata?.localSeq);
|
|
1384
1365
|
this.removePendingChange(serializedInterval);
|
|
1385
1366
|
}
|
|
1386
1367
|
|
|
1387
|
-
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
1388
|
-
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
1389
|
-
// strip it out of the properties here.
|
|
1390
|
-
const { id, properties } = getSerializedProperties(serializedInterval);
|
|
1391
|
-
assert(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1392
|
-
const interval: SequenceIntervalClass | undefined = this.getIntervalById(id);
|
|
1393
1368
|
if (!interval) {
|
|
1394
1369
|
// The interval has been removed locally; no-op.
|
|
1395
1370
|
return;
|
|
@@ -1405,10 +1380,8 @@ export class IntervalCollection
|
|
|
1405
1380
|
let start: number | "start" | "end" | undefined;
|
|
1406
1381
|
let end: number | "start" | "end" | undefined;
|
|
1407
1382
|
// Track pending start/end independently of one another.
|
|
1408
|
-
if (!this.
|
|
1383
|
+
if (!this.hasPendingChanges(id)) {
|
|
1409
1384
|
start = serializedInterval.start;
|
|
1410
|
-
}
|
|
1411
|
-
if (!this.hasPendingChangeEnd(id)) {
|
|
1412
1385
|
end = serializedInterval.end;
|
|
1413
1386
|
}
|
|
1414
1387
|
|
|
@@ -1469,7 +1442,7 @@ export class IntervalCollection
|
|
|
1469
1442
|
public rebaseLocalInterval(
|
|
1470
1443
|
opName: string,
|
|
1471
1444
|
serializedInterval: SerializedIntervalDelta,
|
|
1472
|
-
|
|
1445
|
+
localOpMetadata: IMapMessageLocalMetadata,
|
|
1473
1446
|
): SerializedIntervalDelta | undefined {
|
|
1474
1447
|
if (!this.client) {
|
|
1475
1448
|
// If there's no associated mergeTree client, the originally submitted op is still correct.
|
|
@@ -1479,6 +1452,7 @@ export class IntervalCollection
|
|
|
1479
1452
|
throw new LoggingError("attachSequence must be called");
|
|
1480
1453
|
}
|
|
1481
1454
|
|
|
1455
|
+
const { localSeq } = localOpMetadata;
|
|
1482
1456
|
const { intervalType, properties, stickiness, startSide, endSide } = serializedInterval;
|
|
1483
1457
|
const { id } = getSerializedProperties(serializedInterval);
|
|
1484
1458
|
const { start: startRebased, end: endRebased } =
|
|
@@ -1500,7 +1474,7 @@ export class IntervalCollection
|
|
|
1500
1474
|
if (
|
|
1501
1475
|
opName === "change" &&
|
|
1502
1476
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- ?? is not logically equivalent when .hasPendingChangeStart returns false.
|
|
1503
|
-
|
|
1477
|
+
this.hasPendingChanges(id)
|
|
1504
1478
|
) {
|
|
1505
1479
|
this.removePendingChange(serializedInterval);
|
|
1506
1480
|
this.addPendingChange(id, rebased);
|
|
@@ -1577,19 +1551,15 @@ export class IntervalCollection
|
|
|
1577
1551
|
);
|
|
1578
1552
|
|
|
1579
1553
|
const id = interval.getIntervalId();
|
|
1580
|
-
const
|
|
1581
|
-
const hasPendingEndChange = this.hasPendingChangeEnd(id);
|
|
1554
|
+
const hasPendingChange = this.hasPendingChanges(id);
|
|
1582
1555
|
|
|
1583
|
-
if (!
|
|
1556
|
+
if (!hasPendingChange) {
|
|
1584
1557
|
setSlideOnRemove(interval.start);
|
|
1585
|
-
}
|
|
1586
|
-
|
|
1587
|
-
if (!hasPendingEndChange) {
|
|
1588
1558
|
setSlideOnRemove(interval.end);
|
|
1589
1559
|
}
|
|
1590
1560
|
|
|
1591
|
-
const needsStartUpdate = newStart !== undefined && !
|
|
1592
|
-
const needsEndUpdate = newEnd !== undefined && !
|
|
1561
|
+
const needsStartUpdate = newStart !== undefined && !hasPendingChange;
|
|
1562
|
+
const needsEndUpdate = newEnd !== undefined && !hasPendingChange;
|
|
1593
1563
|
|
|
1594
1564
|
if (needsStartUpdate || needsEndUpdate) {
|
|
1595
1565
|
if (!this.localCollection) {
|
package/src/packageVersion.ts
CHANGED
package/src/sequence.ts
CHANGED
|
@@ -776,7 +776,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
776
776
|
/**
|
|
777
777
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.reSubmitCore}
|
|
778
778
|
*/
|
|
779
|
-
protected reSubmitCore(content: any, localOpMetadata: unknown) {
|
|
779
|
+
protected reSubmitCore(content: any, localOpMetadata: unknown, squash: boolean = false) {
|
|
780
780
|
const originalRefSeq = this.inFlightRefSeqs.shift();
|
|
781
781
|
assert(
|
|
782
782
|
originalRefSeq !== undefined,
|
|
@@ -790,12 +790,16 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
790
790
|
)
|
|
791
791
|
) {
|
|
792
792
|
this.submitSequenceMessage(
|
|
793
|
-
this.client.regeneratePendingOp(content as IMergeTreeOp, localOpMetadata),
|
|
793
|
+
this.client.regeneratePendingOp(content as IMergeTreeOp, localOpMetadata, squash),
|
|
794
794
|
);
|
|
795
795
|
}
|
|
796
796
|
});
|
|
797
797
|
}
|
|
798
798
|
|
|
799
|
+
protected reSubmitSquashed(content: unknown, localOpMetadata: unknown): void {
|
|
800
|
+
this.reSubmitCore(content, localOpMetadata, true);
|
|
801
|
+
}
|
|
802
|
+
|
|
799
803
|
/**
|
|
800
804
|
* Revert an op
|
|
801
805
|
*/
|