@fluidframework/sequence 0.59.4002 → 1.0.2
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 +1 -1
- package/dist/intervalCollection.d.ts +33 -1
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +130 -41
- package/dist/intervalCollection.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 -2
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +6 -6
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.js +1 -1
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/lib/intervalCollection.d.ts +33 -1
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +131 -42
- package/lib/intervalCollection.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 -2
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +7 -7
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.js +1 -1
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/package.json +40 -38
- package/src/intervalCollection.ts +182 -56
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +19 -17
- package/src/sharedIntervalCollection.ts +1 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
|
|
9
9
|
import { IEvent } from "@fluidframework/common-definitions";
|
|
10
|
+
import { UsageError } from "@fluidframework/container-utils";
|
|
10
11
|
import {
|
|
11
12
|
addProperties,
|
|
12
13
|
Client,
|
|
@@ -17,12 +18,14 @@ import {
|
|
|
17
18
|
IntervalConflictResolver,
|
|
18
19
|
IntervalNode,
|
|
19
20
|
IntervalTree,
|
|
21
|
+
ISegment,
|
|
20
22
|
LocalReference,
|
|
21
23
|
MergeTreeDeltaType,
|
|
22
24
|
PropertiesManager,
|
|
23
25
|
PropertySet,
|
|
24
26
|
RedBlackTree,
|
|
25
27
|
ReferenceType,
|
|
28
|
+
refTypeIncludesFlag,
|
|
26
29
|
reservedRangeLabelsKey,
|
|
27
30
|
UnassignedSequenceNumber,
|
|
28
31
|
} from "@fluidframework/merge-tree";
|
|
@@ -35,7 +38,17 @@ const reservedIntervalIdKey = "intervalId";
|
|
|
35
38
|
export enum IntervalType {
|
|
36
39
|
Simple = 0x0,
|
|
37
40
|
Nest = 0x1,
|
|
38
|
-
|
|
41
|
+
/**
|
|
42
|
+
* SlideOnRemove indicates that the ends of the interval will slide if the segment
|
|
43
|
+
* they reference is removed and acked.
|
|
44
|
+
* See `packages\dds\merge-tree\REFERENCEPOSITIONS.md` for details
|
|
45
|
+
* SlideOnRemove is the default interval behavior and does not need to be specified.
|
|
46
|
+
*/
|
|
47
|
+
SlideOnRemove = 0x2, // SlideOnRemove is default behavior - all intervals are SlideOnRemove
|
|
48
|
+
/**
|
|
49
|
+
* @internal
|
|
50
|
+
* A temporary interval, used internally
|
|
51
|
+
*/
|
|
39
52
|
Transient = 0x4,
|
|
40
53
|
}
|
|
41
54
|
|
|
@@ -58,8 +71,26 @@ export interface ISerializableInterval extends IInterval {
|
|
|
58
71
|
|
|
59
72
|
export interface IIntervalHelpers<TInterval extends ISerializableInterval> {
|
|
60
73
|
compareEnds(a: TInterval, b: TInterval): number;
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @param label - label of the interval collection this interval is being added to. This parameter is
|
|
77
|
+
* irrelevant for transient intervals.
|
|
78
|
+
* @param start - numerical start position of the interval
|
|
79
|
+
* @param end - numberical end position of the interval
|
|
80
|
+
* @param client - client creating the interval
|
|
81
|
+
* @param intervalType - Type of interval to create. Default is SlideOnRemove
|
|
82
|
+
* @param op - If this create came from a remote client, op that created it. Default is undefined (i.e. local)
|
|
83
|
+
* @param fromSnapshot - If this create came from loading a snapshot. Default is false.
|
|
84
|
+
*/
|
|
85
|
+
create(
|
|
86
|
+
label: string,
|
|
87
|
+
start: number,
|
|
88
|
+
end: number,
|
|
89
|
+
client: Client,
|
|
90
|
+
intervalType?: IntervalType,
|
|
91
|
+
op?: ISequencedDocumentMessage,
|
|
92
|
+
fromSnapshot?: boolean,
|
|
93
|
+
): TInterval;
|
|
63
94
|
}
|
|
64
95
|
|
|
65
96
|
export class Interval implements ISerializableInterval {
|
|
@@ -310,20 +341,39 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
310
341
|
}
|
|
311
342
|
}
|
|
312
343
|
|
|
313
|
-
function
|
|
344
|
+
function createPositionReferenceFromSegoff(
|
|
314
345
|
client: Client,
|
|
315
|
-
|
|
346
|
+
segoff: { segment: ISegment | undefined; offset: number | undefined; },
|
|
316
347
|
refType: ReferenceType,
|
|
317
348
|
op?: ISequencedDocumentMessage): LocalReference {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
349
|
+
if (segoff.segment) {
|
|
350
|
+
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined);
|
|
351
|
+
return ref as LocalReference;
|
|
352
|
+
} else {
|
|
353
|
+
if (!op && !refTypeIncludesFlag(refType, ReferenceType.Transient)) {
|
|
354
|
+
throw new UsageError("Non-transient references need segment");
|
|
323
355
|
}
|
|
324
|
-
return
|
|
356
|
+
return new LocalReference(client, undefined, 0, refType);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function createPositionReference(
|
|
361
|
+
client: Client,
|
|
362
|
+
pos: number,
|
|
363
|
+
refType: ReferenceType,
|
|
364
|
+
op?: ISequencedDocumentMessage,
|
|
365
|
+
fromSnapshot?: boolean): LocalReference {
|
|
366
|
+
let segoff;
|
|
367
|
+
if (op) {
|
|
368
|
+
assert((refType & ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
|
|
369
|
+
segoff = client.getContainingSegment(pos, op);
|
|
370
|
+
segoff = client.getSlideToSegment(segoff);
|
|
371
|
+
} else {
|
|
372
|
+
assert((refType & ReferenceType.SlideOnRemove) === 0 || fromSnapshot,
|
|
373
|
+
0x2f6 /* SlideOnRemove references must be op created */);
|
|
374
|
+
segoff = client.getContainingSegment(pos);
|
|
325
375
|
}
|
|
326
|
-
return
|
|
376
|
+
return createPositionReferenceFromSegoff(client, segoff, refType, op);
|
|
327
377
|
}
|
|
328
378
|
|
|
329
379
|
function createSequenceInterval(
|
|
@@ -331,38 +381,43 @@ function createSequenceInterval(
|
|
|
331
381
|
start: number,
|
|
332
382
|
end: number,
|
|
333
383
|
client: Client,
|
|
334
|
-
intervalType
|
|
335
|
-
op?: ISequencedDocumentMessage
|
|
384
|
+
intervalType?: IntervalType,
|
|
385
|
+
op?: ISequencedDocumentMessage,
|
|
386
|
+
fromSnapshot?: boolean): SequenceInterval {
|
|
336
387
|
let beginRefType = ReferenceType.RangeBegin;
|
|
337
388
|
let endRefType = ReferenceType.RangeEnd;
|
|
338
|
-
if (intervalType === IntervalType.
|
|
339
|
-
beginRefType = ReferenceType.NestBegin;
|
|
340
|
-
endRefType = ReferenceType.NestEnd;
|
|
341
|
-
} else if (intervalType === IntervalType.Transient) {
|
|
389
|
+
if (intervalType === IntervalType.Transient) {
|
|
342
390
|
beginRefType = ReferenceType.Transient;
|
|
343
391
|
endRefType = ReferenceType.Transient;
|
|
392
|
+
} else {
|
|
393
|
+
if (intervalType === IntervalType.Nest) {
|
|
394
|
+
beginRefType = ReferenceType.NestBegin;
|
|
395
|
+
endRefType = ReferenceType.NestEnd;
|
|
396
|
+
}
|
|
397
|
+
// All non-transient interval references must eventually be SlideOnRemove
|
|
398
|
+
// To ensure eventual consistency, they must start as StayOnRemove when
|
|
399
|
+
// pending (created locally and creation op is not acked)
|
|
400
|
+
if (op || fromSnapshot) {
|
|
401
|
+
beginRefType |= ReferenceType.SlideOnRemove;
|
|
402
|
+
endRefType |= ReferenceType.SlideOnRemove;
|
|
403
|
+
} else {
|
|
404
|
+
beginRefType |= ReferenceType.StayOnRemove;
|
|
405
|
+
endRefType |= ReferenceType.StayOnRemove;
|
|
406
|
+
}
|
|
344
407
|
}
|
|
345
408
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
startLref.pairedRef = endLref;
|
|
356
|
-
endLref.pairedRef = startLref;
|
|
357
|
-
const rangeProp = {
|
|
358
|
-
[reservedRangeLabelsKey]: [label],
|
|
359
|
-
};
|
|
360
|
-
startLref.addProperties(rangeProp);
|
|
361
|
-
endLref.addProperties(rangeProp);
|
|
409
|
+
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot);
|
|
410
|
+
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot);
|
|
411
|
+
startLref.pairedRef = endLref;
|
|
412
|
+
endLref.pairedRef = startLref;
|
|
413
|
+
const rangeProp = {
|
|
414
|
+
[reservedRangeLabelsKey]: [label],
|
|
415
|
+
};
|
|
416
|
+
startLref.addProperties(rangeProp);
|
|
417
|
+
endLref.addProperties(rangeProp);
|
|
362
418
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
419
|
+
const ival = new SequenceInterval(startLref, endLref, intervalType, rangeProp);
|
|
420
|
+
return ival;
|
|
366
421
|
}
|
|
367
422
|
|
|
368
423
|
export function defaultIntervalConflictResolver(a: Interval, b: Interval) {
|
|
@@ -520,20 +575,19 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
520
575
|
}
|
|
521
576
|
|
|
522
577
|
public findOverlappingIntervals(startPosition: number, endPosition: number) {
|
|
523
|
-
if (
|
|
524
|
-
const transientInterval =
|
|
525
|
-
this.helpers.create(
|
|
526
|
-
"transient",
|
|
527
|
-
startPosition,
|
|
528
|
-
endPosition,
|
|
529
|
-
this.client,
|
|
530
|
-
IntervalType.Transient);
|
|
531
|
-
|
|
532
|
-
const overlappingIntervalNodes = this.intervalTree.match(transientInterval);
|
|
533
|
-
return overlappingIntervalNodes.map((node) => node.key);
|
|
534
|
-
} else {
|
|
578
|
+
if (endPosition < startPosition || this.intervalTree.intervals.isEmpty()) {
|
|
535
579
|
return [];
|
|
536
580
|
}
|
|
581
|
+
const transientInterval =
|
|
582
|
+
this.helpers.create(
|
|
583
|
+
"transient",
|
|
584
|
+
startPosition,
|
|
585
|
+
endPosition,
|
|
586
|
+
this.client,
|
|
587
|
+
IntervalType.Transient);
|
|
588
|
+
|
|
589
|
+
const overlappingIntervalNodes = this.intervalTree.match(transientInterval);
|
|
590
|
+
return overlappingIntervalNodes.map((node) => node.key);
|
|
537
591
|
}
|
|
538
592
|
|
|
539
593
|
public previousInterval(pos: number) {
|
|
@@ -855,11 +909,18 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
855
909
|
if (this.savedSerializedIntervals) {
|
|
856
910
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
857
911
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
912
|
+
const { start, end, intervalType, properties } = serializedInterval;
|
|
913
|
+
const interval = this.helpers.create(
|
|
914
|
+
label,
|
|
915
|
+
start,
|
|
916
|
+
end,
|
|
917
|
+
client,
|
|
918
|
+
intervalType,
|
|
919
|
+
undefined,
|
|
920
|
+
true,
|
|
921
|
+
);
|
|
922
|
+
interval.addProperties(properties);
|
|
923
|
+
this.localCollection.add(interval);
|
|
863
924
|
}
|
|
864
925
|
}
|
|
865
926
|
this.savedSerializedIntervals = undefined;
|
|
@@ -872,6 +933,14 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
872
933
|
return this.localCollection.getIntervalById(id);
|
|
873
934
|
}
|
|
874
935
|
|
|
936
|
+
/**
|
|
937
|
+
* Create a new interval and add it to the collection
|
|
938
|
+
* @param start - interval start position
|
|
939
|
+
* @param end - interval end position
|
|
940
|
+
* @param intervalType - type of the interval. All intervals are SlideOnRemove. Intervals may not be Transient.
|
|
941
|
+
* @param props - properties of the interval
|
|
942
|
+
* @returns - the created interval
|
|
943
|
+
*/
|
|
875
944
|
public add(
|
|
876
945
|
start: number,
|
|
877
946
|
end: number,
|
|
@@ -881,6 +950,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
881
950
|
if (!this.attached) {
|
|
882
951
|
throw new Error("attach must be called prior to adding intervals");
|
|
883
952
|
}
|
|
953
|
+
if (intervalType & IntervalType.Transient) {
|
|
954
|
+
throw new Error("Can not add transient intervals");
|
|
955
|
+
}
|
|
884
956
|
|
|
885
957
|
const interval: TInterval = this.localCollection.addInterval(start, end, intervalType, props);
|
|
886
958
|
|
|
@@ -1064,6 +1136,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1064
1136
|
// This is an ack from the server. Remove the pending change.
|
|
1065
1137
|
this.removePendingChange(serializedInterval);
|
|
1066
1138
|
const id: string = serializedInterval.properties[reservedIntervalIdKey];
|
|
1139
|
+
// Could store the interval in the localOpMetadata to avoid the getIntervalById call
|
|
1067
1140
|
interval = this.getIntervalById(id);
|
|
1068
1141
|
if (interval) {
|
|
1069
1142
|
// Let the propertyManager prune its pending change-properties set.
|
|
@@ -1072,6 +1145,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1072
1145
|
type: MergeTreeDeltaType.ANNOTATE,
|
|
1073
1146
|
props: serializedInterval.properties,
|
|
1074
1147
|
});
|
|
1148
|
+
|
|
1149
|
+
this.ackInterval(interval, op);
|
|
1075
1150
|
}
|
|
1076
1151
|
} else {
|
|
1077
1152
|
// If there are pending changes with this ID, don't apply the remote start/end change, as the local ack
|
|
@@ -1130,6 +1205,53 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1130
1205
|
});
|
|
1131
1206
|
}
|
|
1132
1207
|
|
|
1208
|
+
private getSlideToSegment(lref: LocalReference) {
|
|
1209
|
+
const segoff = { segment: lref.segment, offset: lref.offset };
|
|
1210
|
+
const newSegoff = this.client.getSlideToSegment(segoff);
|
|
1211
|
+
const value: { segment: ISegment | undefined; offset: number | undefined; } | undefined
|
|
1212
|
+
= (segoff === newSegoff) ? undefined : newSegoff;
|
|
1213
|
+
return value;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
private setSlideOnRemove(lref: LocalReference) {
|
|
1217
|
+
let refType = lref.refType;
|
|
1218
|
+
refType = refType & ~ReferenceType.StayOnRemove;
|
|
1219
|
+
refType = refType | ReferenceType.SlideOnRemove;
|
|
1220
|
+
lref.refType = refType;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
private ackInterval(interval: TInterval, op: ISequencedDocumentMessage) {
|
|
1224
|
+
// in current usage, interval is always a SequenceInterval
|
|
1225
|
+
if (!(interval instanceof SequenceInterval)) {
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
if (!refTypeIncludesFlag(interval.start, ReferenceType.StayOnRemove)) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
assert(refTypeIncludesFlag(interval.end, ReferenceType.StayOnRemove),
|
|
1233
|
+
0x2f7 /* start and end must both be StayOnRemove */);
|
|
1234
|
+
const newStart = this.getSlideToSegment(interval.start);
|
|
1235
|
+
const newEnd = this.getSlideToSegment(interval.end);
|
|
1236
|
+
this.setSlideOnRemove(interval.start);
|
|
1237
|
+
this.setSlideOnRemove(interval.end);
|
|
1238
|
+
|
|
1239
|
+
if (newStart || newEnd) {
|
|
1240
|
+
this.localCollection.removeExistingInterval(interval);
|
|
1241
|
+
if (newStart) {
|
|
1242
|
+
const props = interval.start.properties;
|
|
1243
|
+
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op);
|
|
1244
|
+
interval.start.addProperties(props);
|
|
1245
|
+
}
|
|
1246
|
+
if (newEnd) {
|
|
1247
|
+
const props = interval.end.properties;
|
|
1248
|
+
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op);
|
|
1249
|
+
interval.end.addProperties(props);
|
|
1250
|
+
}
|
|
1251
|
+
this.localCollection.add(interval);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1133
1255
|
/** @deprecated - use ackAdd */
|
|
1134
1256
|
public addInternal(
|
|
1135
1257
|
serializedInterval: ISerializedInterval,
|
|
@@ -1144,8 +1266,12 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1144
1266
|
local: boolean,
|
|
1145
1267
|
op: ISequencedDocumentMessage) {
|
|
1146
1268
|
if (local) {
|
|
1147
|
-
|
|
1148
|
-
//
|
|
1269
|
+
const id: string = serializedInterval.properties[reservedIntervalIdKey];
|
|
1270
|
+
// Could store the interval in the localOpMetadata to avoid the getIntervalById call
|
|
1271
|
+
const localInterval = this.getIntervalById(id);
|
|
1272
|
+
if (localInterval) {
|
|
1273
|
+
this.ackInterval(localInterval, op);
|
|
1274
|
+
}
|
|
1149
1275
|
return;
|
|
1150
1276
|
}
|
|
1151
1277
|
|
package/src/packageVersion.ts
CHANGED
package/src/sequence.ts
CHANGED
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
SummarySerializer,
|
|
49
49
|
} from "@fluidframework/shared-object-base";
|
|
50
50
|
import { IEventThisPlaceHolder } from "@fluidframework/common-definitions";
|
|
51
|
-
import { ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
|
|
51
|
+
import { ISummaryTreeWithStats, ITelemetryContext } from "@fluidframework/runtime-definitions";
|
|
52
52
|
|
|
53
53
|
import {
|
|
54
54
|
IntervalCollection,
|
|
@@ -173,7 +173,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
173
173
|
attributes: IChannelAttributes,
|
|
174
174
|
public readonly segmentFromSpec: (spec: IJSONSegment) => ISegment,
|
|
175
175
|
) {
|
|
176
|
-
super(id, dataStoreRuntime, attributes);
|
|
176
|
+
super(id, dataStoreRuntime, attributes, "fluid_sequence_");
|
|
177
177
|
|
|
178
178
|
this.loadedDeferred.promise.catch((error) => {
|
|
179
179
|
this.logger.sendErrorEvent({ eventName: "SequenceLoadFailed" }, error);
|
|
@@ -463,7 +463,10 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
463
463
|
return this.intervalCollections.keys();
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
protected summarizeCore(
|
|
466
|
+
protected summarizeCore(
|
|
467
|
+
serializer: IFluidSerializer,
|
|
468
|
+
telemetryContext?: ITelemetryContext,
|
|
469
|
+
): ISummaryTreeWithStats {
|
|
467
470
|
const builder = new SummaryTreeBuilder();
|
|
468
471
|
|
|
469
472
|
// conditionally write the interval collection blob
|
|
@@ -519,7 +522,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
519
522
|
this.client.startOrUpdateCollaboration(this.runtime.clientId);
|
|
520
523
|
}
|
|
521
524
|
|
|
522
|
-
protected onDisconnect() {}
|
|
525
|
+
protected onDisconnect() { }
|
|
523
526
|
|
|
524
527
|
protected reSubmitCore(content: any, localOpMetadata: unknown) {
|
|
525
528
|
if (!this.intervalCollections.trySubmitMessage(content, localOpMetadata as IMapMessageLocalMetadata)) {
|
|
@@ -559,18 +562,17 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
559
562
|
|| m.referenceSequenceNumber < collabWindow.minSeq
|
|
560
563
|
|| m.sequenceNumber <= collabWindow.minSeq
|
|
561
564
|
|| m.sequenceNumber <= collabWindow.currentSeq) {
|
|
562
|
-
throw new Error(`Invalid catchup operations in snapshot: ${
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
})}`);
|
|
565
|
+
throw new Error(`Invalid catchup operations in snapshot: ${JSON.stringify({
|
|
566
|
+
op: {
|
|
567
|
+
seq: m.sequenceNumber,
|
|
568
|
+
minSeq: m.minimumSequenceNumber,
|
|
569
|
+
refSeq: m.referenceSequenceNumber,
|
|
570
|
+
},
|
|
571
|
+
collabWindow: {
|
|
572
|
+
seq: collabWindow.currentSeq,
|
|
573
|
+
minSeq: collabWindow.minSeq,
|
|
574
|
+
},
|
|
575
|
+
})}`);
|
|
574
576
|
}
|
|
575
577
|
this.processMergeTreeMsg(m);
|
|
576
578
|
});
|
|
@@ -666,7 +668,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
666
668
|
// shallow clone the message as we only overwrite top level properties,
|
|
667
669
|
// like referenceSequenceNumber and content only
|
|
668
670
|
stashMessage = {
|
|
669
|
-
...
|
|
671
|
+
...message,
|
|
670
672
|
referenceSequenceNumber: stashMessage.sequenceNumber - 1,
|
|
671
673
|
contents: ops.length !== 1 ? createGroupOp(...ops) : ops[0],
|
|
672
674
|
};
|
|
@@ -117,7 +117,7 @@ export class SharedIntervalCollection
|
|
|
117
117
|
runtime: IFluidDataStoreRuntime,
|
|
118
118
|
attributes: IChannelAttributes,
|
|
119
119
|
) {
|
|
120
|
-
super(id, runtime, attributes);
|
|
120
|
+
super(id, runtime, attributes, "fluid_sharedIntervalCollection_");
|
|
121
121
|
this.intervalCollections = new DefaultMap(
|
|
122
122
|
this.serializer,
|
|
123
123
|
this.handle,
|