@fluidframework/sequence 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.224419
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/.eslintrc.js +9 -11
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +449 -0
- package/README.md +364 -183
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/sequence.api.md +741 -0
- package/dist/{defaultMap.js → defaultMap.cjs} +29 -22
- package/dist/defaultMap.cjs.map +1 -0
- package/dist/defaultMap.d.ts +7 -6
- package/dist/defaultMap.d.ts.map +1 -1
- package/dist/defaultMapInterfaces.cjs +7 -0
- package/dist/defaultMapInterfaces.cjs.map +1 -0
- package/dist/defaultMapInterfaces.d.ts +44 -12
- package/dist/defaultMapInterfaces.d.ts.map +1 -1
- package/dist/index.cjs +60 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +14 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/intervalCollection.cjs +1159 -0
- package/dist/intervalCollection.cjs.map +1 -0
- package/dist/intervalCollection.d.ts +461 -162
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.cjs +66 -0
- package/dist/intervalIndex/endpointInRangeIndex.cjs.map +1 -0
- package/dist/intervalIndex/endpointInRangeIndex.d.ts +34 -0
- package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
- package/dist/intervalIndex/endpointIndex.cjs +47 -0
- package/dist/intervalIndex/endpointIndex.cjs.map +1 -0
- package/dist/intervalIndex/endpointIndex.d.ts +38 -0
- package/dist/intervalIndex/endpointIndex.d.ts.map +1 -0
- package/dist/intervalIndex/idIntervalIndex.cjs +44 -0
- package/dist/intervalIndex/idIntervalIndex.cjs.map +1 -0
- package/dist/intervalIndex/idIntervalIndex.d.ts +18 -0
- package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -0
- package/dist/intervalIndex/index.cjs +24 -0
- package/dist/intervalIndex/index.cjs.map +1 -0
- package/dist/intervalIndex/index.d.ts +13 -0
- package/dist/intervalIndex/index.d.ts.map +1 -0
- package/dist/{defaultMapInterfaces.js → intervalIndex/intervalIndex.cjs} +1 -1
- package/dist/intervalIndex/intervalIndex.cjs.map +1 -0
- package/dist/intervalIndex/intervalIndex.d.ts +30 -0
- package/dist/intervalIndex/intervalIndex.d.ts.map +1 -0
- package/dist/intervalIndex/intervalIndexUtils.cjs +22 -0
- package/dist/intervalIndex/intervalIndexUtils.cjs.map +1 -0
- package/dist/intervalIndex/intervalIndexUtils.d.ts +17 -0
- package/dist/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.cjs +116 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.cjs.map +1 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +44 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.cjs +41 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.cjs.map +1 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +11 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.cjs +7 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.cjs.map +1 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +35 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -0
- package/dist/intervalIndex/startpointInRangeIndex.cjs +66 -0
- package/dist/intervalIndex/startpointInRangeIndex.cjs.map +1 -0
- package/dist/intervalIndex/startpointInRangeIndex.d.ts +34 -0
- package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
- package/dist/intervalTree.cjs +80 -0
- package/dist/intervalTree.cjs.map +1 -0
- package/dist/intervalTree.d.ts +24 -0
- package/dist/intervalTree.d.ts.map +1 -0
- package/dist/intervals/index.cjs +23 -0
- package/dist/intervals/index.cjs.map +1 -0
- package/dist/intervals/index.d.ts +8 -0
- package/dist/intervals/index.d.ts.map +1 -0
- package/dist/intervals/interval.cjs +181 -0
- package/dist/intervals/interval.cjs.map +1 -0
- package/dist/intervals/interval.d.ts +84 -0
- package/dist/intervals/interval.d.ts.map +1 -0
- package/dist/intervals/intervalUtils.cjs +83 -0
- package/dist/intervals/intervalUtils.cjs.map +1 -0
- package/dist/intervals/intervalUtils.d.ts +230 -0
- package/dist/intervals/intervalUtils.d.ts.map +1 -0
- package/dist/intervals/sequenceInterval.cjs +378 -0
- package/dist/intervals/sequenceInterval.cjs.map +1 -0
- package/dist/intervals/sequenceInterval.d.ts +137 -0
- package/dist/intervals/sequenceInterval.d.ts.map +1 -0
- package/dist/{localValues.js → localValues.cjs} +1 -1
- package/dist/localValues.cjs.map +1 -0
- package/dist/localValues.d.ts +2 -1
- package/dist/localValues.d.ts.map +1 -1
- package/dist/{packageVersion.js → packageVersion.cjs} +2 -2
- package/dist/packageVersion.cjs.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/revertibles.cjs +425 -0
- package/dist/revertibles.cjs.map +1 -0
- package/dist/revertibles.d.ts +86 -0
- package/dist/revertibles.d.ts.map +1 -0
- package/dist/sequence-alpha.d.ts +1315 -0
- package/dist/sequence-beta.d.ts +244 -0
- package/dist/sequence-public.d.ts +244 -0
- package/dist/sequence-untrimmed.d.ts +1803 -0
- package/dist/{sequence.js → sequence.cjs} +226 -156
- package/dist/sequence.cjs.map +1 -0
- package/dist/sequence.d.ts +125 -48
- package/dist/sequence.d.ts.map +1 -1
- package/dist/{sequenceDeltaEvent.js → sequenceDeltaEvent.cjs} +18 -8
- package/dist/sequenceDeltaEvent.cjs.map +1 -0
- package/dist/sequenceDeltaEvent.d.ts +24 -7
- package/dist/sequenceDeltaEvent.d.ts.map +1 -1
- package/dist/sequenceFactory.cjs +55 -0
- package/dist/sequenceFactory.cjs.map +1 -0
- package/dist/sequenceFactory.d.ts +3 -89
- package/dist/sequenceFactory.d.ts.map +1 -1
- package/dist/{sharedIntervalCollection.js → sharedIntervalCollection.cjs} +17 -22
- package/dist/sharedIntervalCollection.cjs.map +1 -0
- package/dist/sharedIntervalCollection.d.ts +12 -12
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/{sharedSequence.js → sharedSequence.cjs} +29 -22
- package/dist/sharedSequence.cjs.map +1 -0
- package/dist/sharedSequence.d.ts +14 -2
- package/dist/sharedSequence.d.ts.map +1 -1
- package/dist/sharedString.cjs +286 -0
- package/dist/sharedString.cjs.map +1 -0
- package/dist/sharedString.d.ts +58 -22
- package/dist/sharedString.d.ts.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/{defaultMap.d.ts → defaultMap.d.mts} +7 -6
- package/lib/defaultMap.d.mts.map +1 -0
- package/lib/{defaultMap.js → defaultMap.mjs} +28 -21
- package/lib/defaultMap.mjs.map +1 -0
- package/lib/{defaultMapInterfaces.d.ts → defaultMapInterfaces.d.mts} +44 -12
- package/lib/defaultMapInterfaces.d.mts.map +1 -0
- package/lib/defaultMapInterfaces.mjs +6 -0
- package/lib/defaultMapInterfaces.mjs.map +1 -0
- package/lib/index.d.mts +17 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +16 -0
- package/lib/index.mjs.map +1 -0
- package/lib/intervalCollection.d.mts +569 -0
- package/lib/intervalCollection.d.mts.map +1 -0
- package/lib/intervalCollection.mjs +1144 -0
- package/lib/intervalCollection.mjs.map +1 -0
- package/lib/intervalIndex/endpointInRangeIndex.d.mts +34 -0
- package/lib/intervalIndex/endpointInRangeIndex.d.mts.map +1 -0
- package/lib/intervalIndex/endpointInRangeIndex.mjs +61 -0
- package/lib/intervalIndex/endpointInRangeIndex.mjs.map +1 -0
- package/lib/intervalIndex/endpointIndex.d.mts +38 -0
- package/lib/intervalIndex/endpointIndex.d.mts.map +1 -0
- package/lib/intervalIndex/endpointIndex.mjs +42 -0
- package/lib/intervalIndex/endpointIndex.mjs.map +1 -0
- package/lib/intervalIndex/idIntervalIndex.d.mts +18 -0
- package/lib/intervalIndex/idIntervalIndex.d.mts.map +1 -0
- package/lib/intervalIndex/idIntervalIndex.mjs +40 -0
- package/lib/intervalIndex/idIntervalIndex.mjs.map +1 -0
- package/lib/intervalIndex/index.d.mts +13 -0
- package/lib/intervalIndex/index.d.mts.map +1 -0
- package/lib/intervalIndex/index.mjs +11 -0
- package/lib/intervalIndex/index.mjs.map +1 -0
- package/lib/intervalIndex/intervalIndex.d.mts +30 -0
- package/lib/intervalIndex/intervalIndex.d.mts.map +1 -0
- package/lib/{defaultMapInterfaces.js → intervalIndex/intervalIndex.mjs} +1 -1
- package/lib/intervalIndex/intervalIndex.mjs.map +1 -0
- package/lib/intervalIndex/intervalIndexUtils.d.mts +17 -0
- package/lib/intervalIndex/intervalIndexUtils.d.mts.map +1 -0
- package/lib/intervalIndex/intervalIndexUtils.mjs +18 -0
- package/lib/intervalIndex/intervalIndexUtils.mjs.map +1 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.d.mts +44 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.d.mts.map +1 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.mjs +111 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.mjs.map +1 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.mts +11 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.mts.map +1 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.mjs +37 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.mjs.map +1 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.d.mts +35 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.d.mts.map +1 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.mjs +6 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.mjs.map +1 -0
- package/lib/intervalIndex/startpointInRangeIndex.d.mts +34 -0
- package/lib/intervalIndex/startpointInRangeIndex.d.mts.map +1 -0
- package/lib/intervalIndex/startpointInRangeIndex.mjs +61 -0
- package/lib/intervalIndex/startpointInRangeIndex.mjs.map +1 -0
- package/lib/intervalTree.d.mts +24 -0
- package/lib/intervalTree.d.mts.map +1 -0
- package/lib/intervalTree.mjs +76 -0
- package/lib/intervalTree.mjs.map +1 -0
- package/lib/intervals/index.d.mts +8 -0
- package/lib/intervals/index.d.mts.map +1 -0
- package/lib/intervals/index.mjs +8 -0
- package/lib/intervals/index.mjs.map +1 -0
- package/lib/intervals/interval.d.mts +84 -0
- package/lib/intervals/interval.d.mts.map +1 -0
- package/lib/intervals/interval.mjs +176 -0
- package/lib/intervals/interval.mjs.map +1 -0
- package/lib/intervals/intervalUtils.d.mts +230 -0
- package/lib/intervals/intervalUtils.d.mts.map +1 -0
- package/lib/intervals/intervalUtils.mjs +77 -0
- package/lib/intervals/intervalUtils.mjs.map +1 -0
- package/lib/intervals/sequenceInterval.d.mts +137 -0
- package/lib/intervals/sequenceInterval.d.mts.map +1 -0
- package/lib/intervals/sequenceInterval.mjs +370 -0
- package/lib/intervals/sequenceInterval.mjs.map +1 -0
- package/lib/{localValues.d.ts → localValues.d.mts} +3 -2
- package/lib/localValues.d.mts.map +1 -0
- package/lib/{localValues.js → localValues.mjs} +2 -2
- package/lib/localValues.mjs.map +1 -0
- package/lib/{packageVersion.d.ts → packageVersion.d.mts} +1 -1
- package/lib/{packageVersion.d.ts.map → packageVersion.d.mts.map} +1 -1
- package/lib/{packageVersion.js → packageVersion.mjs} +2 -2
- package/lib/packageVersion.mjs.map +1 -0
- package/lib/revertibles.d.mts +86 -0
- package/lib/revertibles.d.mts.map +1 -0
- package/lib/revertibles.mjs +416 -0
- package/lib/revertibles.mjs.map +1 -0
- package/lib/sequence-alpha.d.mts +1315 -0
- package/lib/sequence-beta.d.mts +244 -0
- package/lib/sequence-public.d.mts +244 -0
- package/lib/sequence-untrimmed.d.mts +1803 -0
- package/lib/{sequence.d.ts → sequence.d.mts} +127 -50
- package/lib/sequence.d.mts.map +1 -0
- package/lib/{sequence.js → sequence.mjs} +225 -152
- package/lib/sequence.mjs.map +1 -0
- package/lib/{sequenceDeltaEvent.d.ts → sequenceDeltaEvent.d.mts} +24 -7
- package/lib/sequenceDeltaEvent.d.mts.map +1 -0
- package/lib/{sequenceDeltaEvent.js → sequenceDeltaEvent.mjs} +20 -8
- package/lib/sequenceDeltaEvent.mjs.map +1 -0
- package/lib/sequenceFactory.d.mts +22 -0
- package/lib/sequenceFactory.d.mts.map +1 -0
- package/lib/sequenceFactory.mjs +51 -0
- package/lib/sequenceFactory.mjs.map +1 -0
- package/lib/{sharedIntervalCollection.d.ts → sharedIntervalCollection.d.mts} +12 -12
- package/lib/sharedIntervalCollection.d.mts.map +1 -0
- package/lib/{sharedIntervalCollection.js → sharedIntervalCollection.mjs} +16 -21
- package/lib/sharedIntervalCollection.mjs.map +1 -0
- package/lib/{sharedSequence.d.ts → sharedSequence.d.mts} +15 -3
- package/lib/sharedSequence.d.mts.map +1 -0
- package/lib/{sharedSequence.js → sharedSequence.mjs} +30 -23
- package/lib/sharedSequence.mjs.map +1 -0
- package/lib/{sharedString.d.ts → sharedString.d.mts} +60 -24
- package/lib/sharedString.d.mts.map +1 -0
- package/lib/sharedString.mjs +281 -0
- package/lib/sharedString.mjs.map +1 -0
- package/package.json +146 -75
- package/prettier.config.cjs +8 -0
- package/sequence.test-files.tar +0 -0
- package/src/defaultMap.ts +417 -403
- package/src/defaultMapInterfaces.ts +157 -117
- package/src/index.ts +86 -26
- package/src/intervalCollection.ts +2043 -1563
- package/src/intervalIndex/endpointInRangeIndex.ts +116 -0
- package/src/intervalIndex/endpointIndex.ts +91 -0
- package/src/intervalIndex/idIntervalIndex.ts +64 -0
- package/src/intervalIndex/index.ts +25 -0
- package/src/intervalIndex/intervalIndex.ts +32 -0
- package/src/intervalIndex/intervalIndexUtils.ts +27 -0
- package/src/intervalIndex/overlappingIntervalsIndex.ts +187 -0
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +80 -0
- package/src/intervalIndex/sequenceIntervalIndexes.ts +34 -0
- package/src/intervalIndex/startpointInRangeIndex.ts +114 -0
- package/src/intervalTree.ts +98 -0
- package/src/intervals/index.ts +25 -0
- package/src/intervals/interval.ts +238 -0
- package/src/intervals/intervalUtils.ts +288 -0
- package/src/intervals/sequenceInterval.ts +616 -0
- package/src/localValues.ts +68 -73
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +693 -0
- package/src/sequence.ts +845 -690
- package/src/sequenceDeltaEvent.ts +164 -131
- package/src/sequenceFactory.ts +58 -214
- package/src/sharedIntervalCollection.ts +161 -152
- package/src/sharedSequence.ts +181 -167
- package/src/sharedString.ts +390 -234
- package/tsc-multi.test.json +10 -0
- package/tsconfig.json +11 -13
- package/.editorconfig +0 -7
- package/.vscode/launch.json +0 -15
- package/dist/defaultMap.js.map +0 -1
- package/dist/defaultMapInterfaces.js.map +0 -1
- package/dist/index.js +0 -44
- package/dist/index.js.map +0 -1
- package/dist/intervalCollection.js +0 -1250
- package/dist/intervalCollection.js.map +0 -1
- package/dist/localValues.js.map +0 -1
- package/dist/packageVersion.js.map +0 -1
- package/dist/sequence.js.map +0 -1
- package/dist/sequenceDeltaEvent.js.map +0 -1
- package/dist/sequenceFactory.js +0 -192
- package/dist/sequenceFactory.js.map +0 -1
- package/dist/sharedIntervalCollection.js.map +0 -1
- package/dist/sharedNumberSequence.d.ts +0 -50
- package/dist/sharedNumberSequence.d.ts.map +0 -1
- package/dist/sharedNumberSequence.js +0 -61
- package/dist/sharedNumberSequence.js.map +0 -1
- package/dist/sharedObjectSequence.d.ts +0 -50
- package/dist/sharedObjectSequence.d.ts.map +0 -1
- package/dist/sharedObjectSequence.js +0 -61
- package/dist/sharedObjectSequence.js.map +0 -1
- package/dist/sharedSequence.js.map +0 -1
- package/dist/sharedString.js +0 -187
- package/dist/sharedString.js.map +0 -1
- package/dist/sparsematrix.d.ts +0 -139
- package/dist/sparsematrix.d.ts.map +0 -1
- package/dist/sparsematrix.js +0 -332
- package/dist/sparsematrix.js.map +0 -1
- package/lib/defaultMap.d.ts.map +0 -1
- package/lib/defaultMap.js.map +0 -1
- package/lib/defaultMapInterfaces.d.ts.map +0 -1
- package/lib/defaultMapInterfaces.js.map +0 -1
- package/lib/index.d.ts +0 -27
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -26
- package/lib/index.js.map +0 -1
- package/lib/intervalCollection.d.ts +0 -270
- package/lib/intervalCollection.d.ts.map +0 -1
- package/lib/intervalCollection.js +0 -1238
- package/lib/intervalCollection.js.map +0 -1
- package/lib/localValues.d.ts.map +0 -1
- package/lib/localValues.js.map +0 -1
- package/lib/packageVersion.js.map +0 -1
- package/lib/sequence.d.ts.map +0 -1
- package/lib/sequence.js.map +0 -1
- package/lib/sequenceDeltaEvent.d.ts.map +0 -1
- package/lib/sequenceDeltaEvent.js.map +0 -1
- package/lib/sequenceFactory.d.ts +0 -108
- package/lib/sequenceFactory.d.ts.map +0 -1
- package/lib/sequenceFactory.js +0 -186
- package/lib/sequenceFactory.js.map +0 -1
- package/lib/sharedIntervalCollection.d.ts.map +0 -1
- package/lib/sharedIntervalCollection.js.map +0 -1
- package/lib/sharedNumberSequence.d.ts +0 -50
- package/lib/sharedNumberSequence.d.ts.map +0 -1
- package/lib/sharedNumberSequence.js +0 -57
- package/lib/sharedNumberSequence.js.map +0 -1
- package/lib/sharedObjectSequence.d.ts +0 -50
- package/lib/sharedObjectSequence.d.ts.map +0 -1
- package/lib/sharedObjectSequence.js +0 -57
- package/lib/sharedObjectSequence.js.map +0 -1
- package/lib/sharedSequence.d.ts.map +0 -1
- package/lib/sharedSequence.js.map +0 -1
- package/lib/sharedString.d.ts.map +0 -1
- package/lib/sharedString.js +0 -183
- package/lib/sharedString.js.map +0 -1
- package/lib/sparsematrix.d.ts +0 -139
- package/lib/sparsematrix.d.ts.map +0 -1
- package/lib/sparsematrix.js +0 -323
- package/lib/sparsematrix.js.map +0 -1
- package/src/sharedNumberSequence.ts +0 -62
- package/src/sharedObjectSequence.ts +0 -62
- package/src/sparsematrix.ts +0 -421
- package/tsconfig.esnext.json +0 -7
|
@@ -2,77 +2,30 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { assert, Deferred } from "@fluidframework/core-utils";
|
|
6
|
+
import { bufferToString } from "@fluid-internal/client-utils";
|
|
7
|
+
import { LoggingError, createChildLogger } from "@fluidframework/telemetry-utils";
|
|
8
|
+
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
9
|
+
import {
|
|
10
|
+
// eslint-disable-next-line import/no-deprecated
|
|
11
|
+
Client, createAnnotateRangeOp,
|
|
12
|
+
// eslint-disable-next-line import/no-deprecated
|
|
13
|
+
createGroupOp, createInsertOp, createRemoveRangeOp, matchProperties, MergeTreeDeltaType, createObliterateRangeOp, } from "@fluidframework/merge-tree";
|
|
9
14
|
import { ObjectStoragePartition, SummaryTreeBuilder } from "@fluidframework/runtime-utils";
|
|
10
15
|
import { makeHandlesSerializable, parseHandles, SharedObject, } from "@fluidframework/shared-object-base";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { SequenceDeltaEvent, SequenceMaintenanceEvent } from "./sequenceDeltaEvent";
|
|
16
|
+
import { DefaultMap } from "./defaultMap.mjs";
|
|
17
|
+
import { SequenceIntervalCollectionValueType, } from "./intervalCollection.mjs";
|
|
18
|
+
import { SequenceDeltaEvent, SequenceMaintenanceEvent } from "./sequenceDeltaEvent.mjs";
|
|
14
19
|
const snapshotFileName = "header";
|
|
15
20
|
const contentPath = "content";
|
|
21
|
+
/**
|
|
22
|
+
* @alpha
|
|
23
|
+
*/
|
|
16
24
|
export class SharedSegmentSequence extends SharedObject {
|
|
17
|
-
constructor(dataStoreRuntime, id, attributes, segmentFromSpec) {
|
|
18
|
-
super(id, dataStoreRuntime, attributes, "fluid_sequence_");
|
|
19
|
-
this.dataStoreRuntime = dataStoreRuntime;
|
|
20
|
-
this.id = id;
|
|
21
|
-
this.segmentFromSpec = segmentFromSpec;
|
|
22
|
-
// Deferred that triggers once the object is loaded
|
|
23
|
-
this.loadedDeferred = new Deferred();
|
|
24
|
-
// cache out going ops created when partial loading
|
|
25
|
-
this.loadedDeferredOutgoingOps = [];
|
|
26
|
-
// cache incoming ops that arrive when partial loading
|
|
27
|
-
this.deferIncomingOps = true;
|
|
28
|
-
this.loadedDeferredIncomingOps = [];
|
|
29
|
-
this.messagesSinceMSNChange = [];
|
|
30
|
-
this.loadedDeferred.promise.catch((error) => {
|
|
31
|
-
this.logger.sendErrorEvent({ eventName: "SequenceLoadFailed" }, error);
|
|
32
|
-
});
|
|
33
|
-
this.client = new Client(segmentFromSpec, ChildLogger.create(this.logger, "SharedSegmentSequence.MergeTreeClient"), dataStoreRuntime.options);
|
|
34
|
-
super.on("newListener", (event) => {
|
|
35
|
-
switch (event) {
|
|
36
|
-
case "sequenceDelta":
|
|
37
|
-
if (!this.client.mergeTreeDeltaCallback) {
|
|
38
|
-
this.client.mergeTreeDeltaCallback = (opArgs, deltaArgs) => {
|
|
39
|
-
this.emit("sequenceDelta", new SequenceDeltaEvent(opArgs, deltaArgs, this.client), this);
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
break;
|
|
43
|
-
case "maintenance":
|
|
44
|
-
if (!this.client.mergeTreeMaintenanceCallback) {
|
|
45
|
-
this.client.mergeTreeMaintenanceCallback = (args, opArgs) => {
|
|
46
|
-
this.emit("maintenance", new SequenceMaintenanceEvent(opArgs, args, this.client), this);
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
break;
|
|
50
|
-
default:
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
super.on("removeListener", (event) => {
|
|
54
|
-
switch (event) {
|
|
55
|
-
case "sequenceDelta":
|
|
56
|
-
if (super.listenerCount(event) === 0) {
|
|
57
|
-
this.client.mergeTreeDeltaCallback = undefined;
|
|
58
|
-
}
|
|
59
|
-
break;
|
|
60
|
-
case "maintenance":
|
|
61
|
-
if (super.listenerCount(event) === 0) {
|
|
62
|
-
this.client.mergeTreeMaintenanceCallback = undefined;
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
default:
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
this.intervalCollections = new DefaultMap(this.serializer, this.handle, (op, localOpMetadata) => this.submitLocalMessage(op, localOpMetadata), new SequenceIntervalCollectionValueType());
|
|
70
|
-
}
|
|
71
25
|
get loaded() {
|
|
72
26
|
return this.loadedDeferred.promise;
|
|
73
27
|
}
|
|
74
28
|
static createOpsFromDelta(event) {
|
|
75
|
-
var _a, _b;
|
|
76
29
|
const ops = [];
|
|
77
30
|
for (const r of event.ranges) {
|
|
78
31
|
switch (event.deltaOperation) {
|
|
@@ -80,14 +33,15 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
80
33
|
const lastAnnotate = ops[ops.length - 1];
|
|
81
34
|
const props = {};
|
|
82
35
|
for (const key of Object.keys(r.propertyDeltas)) {
|
|
83
|
-
props[key] =
|
|
36
|
+
props[key] = r.segment.properties?.[key] ?? null;
|
|
84
37
|
}
|
|
85
|
-
if (lastAnnotate &&
|
|
38
|
+
if (lastAnnotate &&
|
|
39
|
+
lastAnnotate.pos2 === r.position &&
|
|
86
40
|
matchProperties(lastAnnotate.props, props)) {
|
|
87
41
|
lastAnnotate.pos2 += r.segment.cachedLength;
|
|
88
42
|
}
|
|
89
43
|
else {
|
|
90
|
-
ops.push(createAnnotateRangeOp(r.position, r.position + r.segment.cachedLength, props
|
|
44
|
+
ops.push(createAnnotateRangeOp(r.position, r.position + r.segment.cachedLength, props));
|
|
91
45
|
}
|
|
92
46
|
break;
|
|
93
47
|
}
|
|
@@ -96,7 +50,8 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
96
50
|
break;
|
|
97
51
|
case MergeTreeDeltaType.REMOVE: {
|
|
98
52
|
const lastRem = ops[ops.length - 1];
|
|
99
|
-
if (
|
|
53
|
+
if (lastRem?.pos1 === r.position) {
|
|
54
|
+
assert(lastRem.pos2 !== undefined, 0x3ff /* pos2 should not be undefined here */);
|
|
100
55
|
lastRem.pos2 += r.segment.cachedLength;
|
|
101
56
|
}
|
|
102
57
|
else {
|
|
@@ -104,26 +59,94 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
104
59
|
}
|
|
105
60
|
break;
|
|
106
61
|
}
|
|
62
|
+
case MergeTreeDeltaType.OBLITERATE: {
|
|
63
|
+
const lastRem = ops[ops.length - 1];
|
|
64
|
+
if (lastRem?.pos1 === r.position) {
|
|
65
|
+
assert(lastRem.pos2 !== undefined, 0x874 /* pos2 should not be undefined here */);
|
|
66
|
+
lastRem.pos2 += r.segment.cachedLength;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
ops.push(createObliterateRangeOp(r.position, r.position + r.segment.cachedLength));
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
107
73
|
default:
|
|
108
74
|
}
|
|
109
75
|
}
|
|
110
76
|
return ops;
|
|
111
77
|
}
|
|
78
|
+
constructor(dataStoreRuntime, id, attributes, segmentFromSpec) {
|
|
79
|
+
super(id, dataStoreRuntime, attributes, "fluid_sequence_");
|
|
80
|
+
this.dataStoreRuntime = dataStoreRuntime;
|
|
81
|
+
this.id = id;
|
|
82
|
+
this.segmentFromSpec = segmentFromSpec;
|
|
83
|
+
/** `Deferred` that triggers once the object is loaded */
|
|
84
|
+
this.loadedDeferred = new Deferred();
|
|
85
|
+
// cache out going ops created when partial loading
|
|
86
|
+
this.loadedDeferredOutgoingOps = [];
|
|
87
|
+
// cache incoming ops that arrive when partial loading
|
|
88
|
+
this.deferIncomingOps = true;
|
|
89
|
+
this.loadedDeferredIncomingOps = [];
|
|
90
|
+
this.messagesSinceMSNChange = [];
|
|
91
|
+
this.guardReentrancy =
|
|
92
|
+
dataStoreRuntime.options.sharedStringPreventReentrancy ?? true
|
|
93
|
+
? ensureNoReentrancy
|
|
94
|
+
: createReentrancyDetector((depth) => {
|
|
95
|
+
if (totalReentrancyLogs > 0) {
|
|
96
|
+
totalReentrancyLogs--;
|
|
97
|
+
this.logger.sendTelemetryEvent({ eventName: "LocalOpReentry", depth }, new LoggingError(reentrancyErrorMessage));
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
this.loadedDeferred.promise.catch((error) => {
|
|
101
|
+
this.logger.sendErrorEvent({ eventName: "SequenceLoadFailed" }, error);
|
|
102
|
+
});
|
|
103
|
+
// eslint-disable-next-line import/no-deprecated
|
|
104
|
+
this.client = new Client(segmentFromSpec, createChildLogger({
|
|
105
|
+
logger: this.logger,
|
|
106
|
+
namespace: "SharedSegmentSequence.MergeTreeClient",
|
|
107
|
+
}), dataStoreRuntime.options);
|
|
108
|
+
this.client.prependListener("delta", (opArgs, deltaArgs) => {
|
|
109
|
+
const event = new SequenceDeltaEvent(opArgs, deltaArgs, this.client);
|
|
110
|
+
if (opArgs.stashed !== true && event.isLocal) {
|
|
111
|
+
this.submitSequenceMessage(opArgs.op);
|
|
112
|
+
}
|
|
113
|
+
this.emit("sequenceDelta", event, this);
|
|
114
|
+
});
|
|
115
|
+
this.client.on("maintenance", (args, opArgs) => {
|
|
116
|
+
this.emit("maintenance", new SequenceMaintenanceEvent(opArgs, args, this.client), this);
|
|
117
|
+
});
|
|
118
|
+
this.intervalCollections = new DefaultMap(this.serializer, this.handle, (op, localOpMetadata) => this.submitLocalMessage(op, localOpMetadata), new SequenceIntervalCollectionValueType(), dataStoreRuntime.options);
|
|
119
|
+
}
|
|
112
120
|
/**
|
|
113
121
|
* @param start - The inclusive start of the range to remove
|
|
114
122
|
* @param end - The exclusive end of the range to remove
|
|
115
123
|
*/
|
|
116
124
|
removeRange(start, end) {
|
|
117
|
-
|
|
118
|
-
if (removeOp) {
|
|
119
|
-
this.submitSequenceMessage(removeOp);
|
|
120
|
-
}
|
|
121
|
-
return removeOp;
|
|
125
|
+
this.guardReentrancy(() => this.client.removeRangeLocal(start, end));
|
|
122
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Obliterate is similar to remove, but differs in that segments concurrently
|
|
129
|
+
* inserted into an obliterated range will also be removed
|
|
130
|
+
*
|
|
131
|
+
* @param start - The inclusive start of the range to obliterate
|
|
132
|
+
* @param end - The exclusive end of the range to obliterate
|
|
133
|
+
*/
|
|
134
|
+
obliterateRange(start, end) {
|
|
135
|
+
this.guardReentrancy(() => this.client.obliterateRangeLocal(start, end));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* @deprecated The ability to create group ops will be removed in an upcoming
|
|
139
|
+
* release, as group ops are redundant with the native batching capabilities
|
|
140
|
+
* of the runtime
|
|
141
|
+
*/
|
|
123
142
|
groupOperation(groupOp) {
|
|
124
|
-
this.client.localTransaction(groupOp);
|
|
125
|
-
this.submitSequenceMessage(groupOp);
|
|
143
|
+
this.guardReentrancy(() => this.client.localTransaction(groupOp));
|
|
126
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Finds the segment information (i.e. segment + offset) corresponding to a character position in the SharedString.
|
|
147
|
+
* If the position is past the end of the string, `segment` and `offset` on the returned object may be undefined.
|
|
148
|
+
* @param pos - Character position (index) into the current local view of the SharedString.
|
|
149
|
+
*/
|
|
127
150
|
getContainingSegment(pos) {
|
|
128
151
|
return this.client.getContainingSegment(pos);
|
|
129
152
|
}
|
|
@@ -147,14 +170,10 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
147
170
|
* @param start - The inclusive start position of the range to annotate
|
|
148
171
|
* @param end - The exclusive end position of the range to annotate
|
|
149
172
|
* @param props - The properties to annotate the range with
|
|
150
|
-
* @param combiningOp - Optional. Specifies how to combine values for the property, such as "incr" for increment.
|
|
151
173
|
*
|
|
152
174
|
*/
|
|
153
|
-
annotateRange(start, end, props
|
|
154
|
-
|
|
155
|
-
if (annotateOp) {
|
|
156
|
-
this.submitSequenceMessage(annotateOp);
|
|
157
|
-
}
|
|
175
|
+
annotateRange(start, end, props) {
|
|
176
|
+
this.guardReentrancy(() => this.client.annotateRangeLocal(start, end, props));
|
|
158
177
|
}
|
|
159
178
|
getPropertiesAtPosition(pos) {
|
|
160
179
|
return this.client.getPropertiesAtPosition(pos);
|
|
@@ -163,27 +182,28 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
163
182
|
return this.client.getRangeExtentsOfPosition(pos);
|
|
164
183
|
}
|
|
165
184
|
/**
|
|
166
|
-
*
|
|
185
|
+
* Creates a `LocalReferencePosition` on this SharedString. If the refType does not include
|
|
186
|
+
* ReferenceType.Transient, the returned reference will be added to the localRefs on the provided segment.
|
|
187
|
+
* @param segment - Segment to add the local reference on
|
|
188
|
+
* @param offset - Offset on the segment at which to place the local reference
|
|
189
|
+
* @param refType - ReferenceType for the created local reference
|
|
190
|
+
* @param properties - PropertySet to place on the created local reference
|
|
167
191
|
*/
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (refType !== ReferenceType.Transient) {
|
|
171
|
-
this.addLocalReference(lref);
|
|
172
|
-
}
|
|
173
|
-
return lref;
|
|
174
|
-
}
|
|
175
|
-
createLocalReferencePosition(segment, offset, refType, properties) {
|
|
176
|
-
return this.client.createLocalReferencePosition(segment, offset, refType, properties);
|
|
192
|
+
createLocalReferencePosition(segment, offset, refType, properties, slidingPreference, canSlideToEndpoint) {
|
|
193
|
+
return this.client.createLocalReferencePosition(segment, offset, refType, properties, slidingPreference, canSlideToEndpoint);
|
|
177
194
|
}
|
|
178
195
|
/**
|
|
179
|
-
*
|
|
196
|
+
* Resolves a `ReferencePosition` into a character position using this client's perspective.
|
|
180
197
|
*/
|
|
181
|
-
localRefToPos(localRef) {
|
|
182
|
-
return this.client.localReferencePositionToPosition(localRef);
|
|
183
|
-
}
|
|
184
198
|
localReferencePositionToPosition(lref) {
|
|
185
199
|
return this.client.localReferencePositionToPosition(lref);
|
|
186
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Removes a `LocalReferencePosition` from this SharedString.
|
|
203
|
+
*/
|
|
204
|
+
removeLocalReferencePosition(lref) {
|
|
205
|
+
return this.client.removeLocalReferencePosition(lref);
|
|
206
|
+
}
|
|
187
207
|
/**
|
|
188
208
|
* Resolves a remote client's position against the local sequence
|
|
189
209
|
* and returns the remote client's position relative to the local
|
|
@@ -209,29 +229,14 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
209
229
|
const metadata = this.client.peekPendingSegmentGroups(message.type === MergeTreeDeltaType.GROUP ? message.ops.length : 1);
|
|
210
230
|
// if loading isn't complete, we need to cache
|
|
211
231
|
// local ops until loading is complete, and then
|
|
212
|
-
// they will be
|
|
232
|
+
// they will be present
|
|
213
233
|
if (!this.loadedDeferred.isCompleted) {
|
|
214
|
-
this.loadedDeferredOutgoingOps.push([translated, metadata]);
|
|
234
|
+
this.loadedDeferredOutgoingOps.push(metadata ? [translated, metadata] : translated);
|
|
215
235
|
}
|
|
216
236
|
else {
|
|
217
237
|
this.submitLocalMessage(translated, metadata);
|
|
218
238
|
}
|
|
219
239
|
}
|
|
220
|
-
/**
|
|
221
|
-
* @deprecated - use createLocalReferencePosition
|
|
222
|
-
*/
|
|
223
|
-
addLocalReference(lref) {
|
|
224
|
-
return this.client.addLocalReference(lref);
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* @deprecated - use removeLocalReferencePosition
|
|
228
|
-
*/
|
|
229
|
-
removeLocalReference(lref) {
|
|
230
|
-
return this.client.removeLocalReferencePosition(lref);
|
|
231
|
-
}
|
|
232
|
-
removeLocalReferencePosition(lref) {
|
|
233
|
-
return this.client.removeLocalReferencePosition(lref);
|
|
234
|
-
}
|
|
235
240
|
/**
|
|
236
241
|
* Given a position specified relative to a marker id, lookup the marker
|
|
237
242
|
* and convert the position to a character position.
|
|
@@ -242,53 +247,70 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
242
247
|
}
|
|
243
248
|
/**
|
|
244
249
|
* Walk the underlying segments of the sequence.
|
|
245
|
-
* The walked segments may extend beyond the range
|
|
246
|
-
*
|
|
247
|
-
* Set split range to true to ensure only segments within the
|
|
248
|
-
* range are walked.
|
|
250
|
+
* The walked segments may extend beyond the range if the segments cross the
|
|
251
|
+
* ranges start or end boundaries.
|
|
249
252
|
*
|
|
250
|
-
*
|
|
253
|
+
* Set split range to true to ensure only segments within the range are walked.
|
|
254
|
+
*
|
|
255
|
+
* @param handler - The function to handle each segment. Traversal ends if
|
|
256
|
+
* this function returns true.
|
|
251
257
|
* @param start - Optional. The start of range walk.
|
|
252
258
|
* @param end - Optional. The end of range walk
|
|
253
259
|
* @param accum - Optional. An object that will be passed to the handler for accumulation
|
|
254
260
|
* @param splitRange - Optional. Splits boundary segments on the range boundaries
|
|
255
261
|
*/
|
|
256
262
|
walkSegments(handler, start, end, accum, splitRange = false) {
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
getStackContext(startPos, rangeLabels) {
|
|
260
|
-
return this.client.getStackContext(startPos, rangeLabels);
|
|
263
|
+
this.client.walkSegments(handler, start, end, accum, splitRange);
|
|
261
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* @returns The most recent sequence number which has been acked by the server and processed by this
|
|
267
|
+
* SharedSegmentSequence.
|
|
268
|
+
*/
|
|
262
269
|
getCurrentSeq() {
|
|
263
270
|
return this.client.getCurrentSeq();
|
|
264
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* Inserts a segment directly before a `ReferencePosition`.
|
|
274
|
+
* @param refPos - The reference position to insert the segment at
|
|
275
|
+
* @param segment - The segment to insert
|
|
276
|
+
*/
|
|
265
277
|
insertAtReferencePosition(pos, segment) {
|
|
266
|
-
|
|
267
|
-
if (insertOp) {
|
|
268
|
-
this.submitSequenceMessage(insertOp);
|
|
269
|
-
}
|
|
278
|
+
this.guardReentrancy(() => this.client.insertAtReferencePositionLocal(pos, segment));
|
|
270
279
|
}
|
|
271
280
|
/**
|
|
272
|
-
*
|
|
273
|
-
*
|
|
281
|
+
* Inserts a segment
|
|
282
|
+
* @param start - The position to insert the segment at
|
|
283
|
+
* @param spec - The segment to inserts spec
|
|
274
284
|
*/
|
|
275
|
-
|
|
276
|
-
|
|
285
|
+
insertFromSpec(pos, spec) {
|
|
286
|
+
const segment = this.segmentFromSpec(spec);
|
|
287
|
+
this.guardReentrancy(() => this.client.insertSegmentLocal(pos, segment));
|
|
277
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Retrieves the interval collection keyed on `label`. If no such interval collection exists,
|
|
291
|
+
* creates one.
|
|
292
|
+
*/
|
|
278
293
|
getIntervalCollection(label) {
|
|
279
294
|
return this.intervalCollections.get(label);
|
|
280
295
|
}
|
|
281
296
|
/**
|
|
282
|
-
* @returns
|
|
283
|
-
*
|
|
297
|
+
* @returns An iterable object that enumerates the IntervalCollection labels.
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
*
|
|
301
|
+
* ```typescript
|
|
284
302
|
* const iter = this.getIntervalCollectionKeys();
|
|
285
303
|
* for (key of iter)
|
|
286
304
|
* const collection = this.getIntervalCollection(key);
|
|
287
305
|
* ...
|
|
288
|
-
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
289
308
|
getIntervalCollectionLabels() {
|
|
290
309
|
return this.intervalCollections.keys();
|
|
291
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.summarizeCore}
|
|
313
|
+
*/
|
|
292
314
|
summarizeCore(serializer, telemetryContext) {
|
|
293
315
|
const builder = new SummaryTreeBuilder();
|
|
294
316
|
// conditionally write the interval collection blob
|
|
@@ -325,19 +347,24 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
325
347
|
const insert = this.client.insertSegmentLocal(insertIndex, segment);
|
|
326
348
|
if (insert) {
|
|
327
349
|
if (start < end) {
|
|
328
|
-
|
|
329
|
-
this.submitSequenceMessage(createGroupOp(insert, remove));
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
this.submitSequenceMessage(insert);
|
|
350
|
+
this.client.removeRangeLocal(start, end);
|
|
333
351
|
}
|
|
334
352
|
}
|
|
335
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.onConnect}
|
|
356
|
+
*/
|
|
336
357
|
onConnect() {
|
|
337
358
|
// Update merge tree collaboration information with new client ID and then resend pending ops
|
|
338
359
|
this.client.startOrUpdateCollaboration(this.runtime.clientId);
|
|
339
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.onDisconnect}
|
|
363
|
+
*/
|
|
340
364
|
onDisconnect() { }
|
|
365
|
+
/**
|
|
366
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.reSubmitCore}
|
|
367
|
+
*/
|
|
341
368
|
reSubmitCore(content, localOpMetadata) {
|
|
342
369
|
if (!this.intervalCollections.tryResubmitMessage(content, localOpMetadata)) {
|
|
343
370
|
this.submitSequenceMessage(this.client.regeneratePendingOp(content, localOpMetadata));
|
|
@@ -347,7 +374,6 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
347
374
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
|
|
348
375
|
*/
|
|
349
376
|
async loadCore(storage) {
|
|
350
|
-
var _a;
|
|
351
377
|
if (await storage.contains(snapshotFileName)) {
|
|
352
378
|
const blob = await storage.readBlob(snapshotFileName);
|
|
353
379
|
const header = bufferToString(blob, "utf8");
|
|
@@ -364,10 +390,11 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
364
390
|
.then((msgs) => {
|
|
365
391
|
msgs.forEach((m) => {
|
|
366
392
|
const collabWindow = this.client.getCollabWindow();
|
|
367
|
-
if (m.minimumSequenceNumber < collabWindow.minSeq
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
393
|
+
if (m.minimumSequenceNumber < collabWindow.minSeq ||
|
|
394
|
+
m.referenceSequenceNumber < collabWindow.minSeq ||
|
|
395
|
+
m.sequenceNumber <= collabWindow.minSeq ||
|
|
396
|
+
// sequenceNumber could be the same if messages are part of a grouped batch
|
|
397
|
+
m.sequenceNumber < collabWindow.currentSeq) {
|
|
371
398
|
throw new Error(`Invalid catchup operations in snapshot: ${JSON.stringify({
|
|
372
399
|
op: {
|
|
373
400
|
seq: m.sequenceNumber,
|
|
@@ -387,7 +414,7 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
387
414
|
.catch((error) => {
|
|
388
415
|
this.loadFinished(error);
|
|
389
416
|
});
|
|
390
|
-
if (
|
|
417
|
+
if (this.dataStoreRuntime.options?.sequenceInitializeFromHeaderOnly !== true) {
|
|
391
418
|
// if we not doing partial load, await the catch up ops,
|
|
392
419
|
// and the finalization of the load
|
|
393
420
|
await loadCatchUpOps;
|
|
@@ -397,6 +424,9 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
397
424
|
this.loadFinished(error);
|
|
398
425
|
}
|
|
399
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.processCore}
|
|
429
|
+
*/
|
|
400
430
|
processCore(message, local, localOpMetadata) {
|
|
401
431
|
// if loading isn't complete, we need to cache all
|
|
402
432
|
// incoming ops to be applied after loading is complete
|
|
@@ -412,14 +442,19 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
412
442
|
}
|
|
413
443
|
}
|
|
414
444
|
}
|
|
445
|
+
/**
|
|
446
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.didAttach}
|
|
447
|
+
*/
|
|
415
448
|
didAttach() {
|
|
416
|
-
var _a;
|
|
417
449
|
// If we are not local, and we've attached we need to start generating and sending ops
|
|
418
450
|
// so start collaboration and provide a default client id incase we are not connected
|
|
419
451
|
if (this.isAttached()) {
|
|
420
|
-
this.client.startOrUpdateCollaboration(
|
|
452
|
+
this.client.startOrUpdateCollaboration(this.runtime.clientId ?? "attached");
|
|
421
453
|
}
|
|
422
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.initializeLocalCore}
|
|
457
|
+
*/
|
|
423
458
|
initializeLocalCore() {
|
|
424
459
|
super.initializeLocalCore();
|
|
425
460
|
this.loadFinished();
|
|
@@ -428,18 +463,19 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
428
463
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
429
464
|
*/
|
|
430
465
|
applyStashedOp(content) {
|
|
431
|
-
return this.client.applyStashedOp(content);
|
|
466
|
+
return this.client.applyStashedOp(parseHandles(content, this.serializer));
|
|
432
467
|
}
|
|
433
468
|
summarizeMergeTree(serializer) {
|
|
434
469
|
// Are we fully loaded? If not, things will go south
|
|
435
470
|
assert(this.loadedDeferred.isCompleted, 0x074 /* "Snapshot called when not fully loaded" */);
|
|
436
471
|
const minSeq = this.runtime.deltaManager.minimumSequenceNumber;
|
|
437
472
|
this.processMinSequenceNumberChanged(minSeq);
|
|
438
|
-
this.messagesSinceMSNChange.forEach((m) => {
|
|
473
|
+
this.messagesSinceMSNChange.forEach((m) => {
|
|
474
|
+
m.minimumSequenceNumber = minSeq;
|
|
475
|
+
});
|
|
439
476
|
return this.client.summarize(this.runtime, this.handle, serializer, this.messagesSinceMSNChange);
|
|
440
477
|
}
|
|
441
478
|
processMergeTreeMsg(rawMessage, local) {
|
|
442
|
-
var _a, _b;
|
|
443
479
|
const message = parseHandles(rawMessage, this.serializer);
|
|
444
480
|
const ops = [];
|
|
445
481
|
function transformOps(event) {
|
|
@@ -447,23 +483,28 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
447
483
|
}
|
|
448
484
|
const needsTransformation = message.referenceSequenceNumber !== message.sequenceNumber - 1;
|
|
449
485
|
let stashMessage = message;
|
|
450
|
-
if (
|
|
486
|
+
if (this.runtime.options?.newMergeTreeSnapshotFormat !== true) {
|
|
451
487
|
if (needsTransformation) {
|
|
452
488
|
this.on("sequenceDelta", transformOps);
|
|
453
489
|
}
|
|
454
490
|
}
|
|
455
491
|
this.client.applyMsg(message, local);
|
|
456
|
-
if (
|
|
492
|
+
if (this.runtime.options?.newMergeTreeSnapshotFormat !== true) {
|
|
457
493
|
if (needsTransformation) {
|
|
458
494
|
this.removeListener("sequenceDelta", transformOps);
|
|
459
495
|
// shallow clone the message as we only overwrite top level properties,
|
|
460
496
|
// like referenceSequenceNumber and content only
|
|
461
|
-
stashMessage =
|
|
497
|
+
stashMessage = {
|
|
498
|
+
...message,
|
|
499
|
+
referenceSequenceNumber: stashMessage.sequenceNumber - 1,
|
|
500
|
+
// eslint-disable-next-line import/no-deprecated
|
|
501
|
+
contents: ops.length !== 1 ? createGroupOp(...ops) : ops[0],
|
|
502
|
+
};
|
|
462
503
|
}
|
|
463
504
|
this.messagesSinceMSNChange.push(stashMessage);
|
|
464
505
|
// Do GC every once in a while...
|
|
465
|
-
if (this.messagesSinceMSNChange.length > 20
|
|
466
|
-
|
|
506
|
+
if (this.messagesSinceMSNChange.length > 20 &&
|
|
507
|
+
this.messagesSinceMSNChange[20].sequenceNumber < message.minimumSequenceNumber) {
|
|
467
508
|
this.processMinSequenceNumberChanged(message.minimumSequenceNumber);
|
|
468
509
|
}
|
|
469
510
|
}
|
|
@@ -523,4 +564,36 @@ export class SharedSegmentSequence extends SharedObject {
|
|
|
523
564
|
}
|
|
524
565
|
}
|
|
525
566
|
}
|
|
526
|
-
|
|
567
|
+
function createReentrancyDetector(onReentrancy) {
|
|
568
|
+
let depth = 0;
|
|
569
|
+
function detectReentrancy(callback) {
|
|
570
|
+
if (depth > 0) {
|
|
571
|
+
onReentrancy(depth);
|
|
572
|
+
}
|
|
573
|
+
depth++;
|
|
574
|
+
try {
|
|
575
|
+
return callback();
|
|
576
|
+
}
|
|
577
|
+
finally {
|
|
578
|
+
depth--;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return detectReentrancy;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Apps which generate reentrant behavior may do so at a high frequency.
|
|
585
|
+
* Logging even per-SharedSegmentSequence instance might be too noisy, and having a few logs from a session
|
|
586
|
+
* is likely enough.
|
|
587
|
+
*/
|
|
588
|
+
let totalReentrancyLogs = 3;
|
|
589
|
+
/**
|
|
590
|
+
* Resets the reentrancy log counter. Test-only API.
|
|
591
|
+
*/
|
|
592
|
+
export function resetReentrancyLogCounter() {
|
|
593
|
+
totalReentrancyLogs = 3;
|
|
594
|
+
}
|
|
595
|
+
const reentrancyErrorMessage = "Reentrancy detected in sequence local ops";
|
|
596
|
+
const ensureNoReentrancy = createReentrancyDetector(() => {
|
|
597
|
+
throw new LoggingError(reentrancyErrorMessage);
|
|
598
|
+
});
|
|
599
|
+
//# sourceMappingURL=sequence.mjs.map
|