@fluidframework/sequence 0.59.3002 → 0.59.4000-71130
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/dist/{mapKernel.d.ts → defaultMap.d.ts} +21 -145
- package/dist/defaultMap.d.ts.map +1 -0
- package/dist/defaultMap.js +317 -0
- package/dist/defaultMap.js.map +1 -0
- package/dist/{mapKernelInterfaces.d.ts → defaultMapInterfaces.d.ts} +9 -51
- package/dist/defaultMapInterfaces.d.ts.map +1 -0
- package/dist/{mapKernelInterfaces.js → defaultMapInterfaces.js} +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +12 -3
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +44 -39
- package/dist/intervalCollection.js.map +1 -1
- package/dist/localValues.d.ts +7 -86
- package/dist/localValues.d.ts.map +1 -1
- package/dist/localValues.js +1 -131
- package/dist/localValues.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 +5 -1
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +23 -23
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +13 -5
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js +16 -12
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/lib/{mapKernel.d.ts → defaultMap.d.ts} +21 -145
- package/lib/defaultMap.d.ts.map +1 -0
- package/lib/defaultMap.js +313 -0
- package/lib/defaultMap.js.map +1 -0
- package/lib/{mapKernelInterfaces.d.ts → defaultMapInterfaces.d.ts} +9 -51
- package/lib/defaultMapInterfaces.d.ts.map +1 -0
- package/lib/{mapKernelInterfaces.js → defaultMapInterfaces.js} +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +12 -3
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +44 -39
- package/lib/intervalCollection.js.map +1 -1
- package/lib/localValues.d.ts +7 -86
- package/lib/localValues.d.ts.map +1 -1
- package/lib/localValues.js +1 -129
- package/lib/localValues.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 +5 -1
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +23 -23
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +13 -5
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js +16 -12
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/package.json +23 -18
- package/src/defaultMap.ts +453 -0
- package/src/{mapKernelInterfaces.ts → defaultMapInterfaces.ts} +14 -59
- package/src/index.ts +1 -1
- package/src/intervalCollection.ts +58 -43
- package/src/localValues.ts +6 -154
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +32 -33
- package/src/sharedIntervalCollection.ts +22 -25
- package/dist/mapKernel.d.ts.map +0 -1
- package/dist/mapKernel.js +0 -599
- package/dist/mapKernel.js.map +0 -1
- package/dist/mapKernelInterfaces.d.ts.map +0 -1
- package/dist/mapKernelInterfaces.js.map +0 -1
- package/lib/mapKernel.d.ts.map +0 -1
- package/lib/mapKernel.js +0 -595
- package/lib/mapKernel.js.map +0 -1
- package/lib/mapKernelInterfaces.d.ts.map +0 -1
- package/lib/mapKernelInterfaces.js.map +0 -1
- package/src/mapKernel.ts +0 -850
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from "@fluidframework/merge-tree";
|
|
29
29
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
30
30
|
import { v4 as uuid } from "uuid";
|
|
31
|
-
import { IValueFactory, IValueOpEmitter, IValueOperation, IValueType } from "./
|
|
31
|
+
import { IValueFactory, IValueOpEmitter, IValueOperation, IValueType } from "./defaultMapInterfaces";
|
|
32
32
|
|
|
33
33
|
const reservedIntervalIdKey = "intervalId";
|
|
34
34
|
|
|
@@ -684,12 +684,7 @@ export class SequenceIntervalCollectionValueType
|
|
|
684
684
|
"add",
|
|
685
685
|
{
|
|
686
686
|
process: (value, params, local, op) => {
|
|
687
|
-
|
|
688
|
-
if (local) {
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
value.addInternal(params, local, op);
|
|
687
|
+
value.ackAdd(params, local, op);
|
|
693
688
|
},
|
|
694
689
|
},
|
|
695
690
|
],
|
|
@@ -697,10 +692,7 @@ export class SequenceIntervalCollectionValueType
|
|
|
697
692
|
"delete",
|
|
698
693
|
{
|
|
699
694
|
process: (value, params, local, op) => {
|
|
700
|
-
|
|
701
|
-
return;
|
|
702
|
-
}
|
|
703
|
-
value.deleteInterval(params, local, op);
|
|
695
|
+
value.ackDelete(params, local, op);
|
|
704
696
|
},
|
|
705
697
|
},
|
|
706
698
|
],
|
|
@@ -708,7 +700,7 @@ export class SequenceIntervalCollectionValueType
|
|
|
708
700
|
"change",
|
|
709
701
|
{
|
|
710
702
|
process: (value, params, local, op) => {
|
|
711
|
-
value.
|
|
703
|
+
value.ackChange(params, local, op);
|
|
712
704
|
},
|
|
713
705
|
},
|
|
714
706
|
]]);
|
|
@@ -767,12 +759,7 @@ export class IntervalCollectionValueType
|
|
|
767
759
|
"add",
|
|
768
760
|
{
|
|
769
761
|
process: (value, params, local, op) => {
|
|
770
|
-
|
|
771
|
-
if (local) {
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
value.addInternal(params, local, op);
|
|
762
|
+
value.ackAdd(params, local, op);
|
|
776
763
|
},
|
|
777
764
|
},
|
|
778
765
|
],
|
|
@@ -780,10 +767,7 @@ export class IntervalCollectionValueType
|
|
|
780
767
|
"delete",
|
|
781
768
|
{
|
|
782
769
|
process: (value, params, local, op) => {
|
|
783
|
-
|
|
784
|
-
return;
|
|
785
|
-
}
|
|
786
|
-
value.deleteInterval(params, local, op);
|
|
770
|
+
value.ackDelete(params, local, op);
|
|
787
771
|
},
|
|
788
772
|
},
|
|
789
773
|
],
|
|
@@ -791,7 +775,7 @@ export class IntervalCollectionValueType
|
|
|
791
775
|
"change",
|
|
792
776
|
{
|
|
793
777
|
process: (value, params, local, op) => {
|
|
794
|
-
value.
|
|
778
|
+
value.ackChange(params, local, op);
|
|
795
779
|
},
|
|
796
780
|
},
|
|
797
781
|
]]);
|
|
@@ -842,8 +826,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
842
826
|
private localCollection: LocalIntervalCollection<TInterval>;
|
|
843
827
|
private onDeserialize: DeserializeCallback;
|
|
844
828
|
private client: Client;
|
|
845
|
-
private
|
|
846
|
-
private
|
|
829
|
+
private pendingChangesStart: Map<string, ISerializedInterval[]>;
|
|
830
|
+
private pendingChangesEnd: Map<string, ISerializedInterval[]>;
|
|
847
831
|
|
|
848
832
|
public get attached(): boolean {
|
|
849
833
|
return !!this.localCollection;
|
|
@@ -998,16 +982,16 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
998
982
|
|
|
999
983
|
private addPendingChange(id: string, serializedInterval: ISerializedInterval) {
|
|
1000
984
|
if (serializedInterval.start !== undefined) {
|
|
1001
|
-
if (!this.
|
|
1002
|
-
this.
|
|
985
|
+
if (!this.pendingChangesStart) {
|
|
986
|
+
this.pendingChangesStart = new Map<string, ISerializedInterval[]>();
|
|
1003
987
|
}
|
|
1004
|
-
this.addPendingChangeHelper(id, this.
|
|
988
|
+
this.addPendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
1005
989
|
}
|
|
1006
990
|
if (serializedInterval.end !== undefined) {
|
|
1007
|
-
if (!this.
|
|
1008
|
-
this.
|
|
991
|
+
if (!this.pendingChangesEnd) {
|
|
992
|
+
this.pendingChangesEnd = new Map<string, ISerializedInterval[]>();
|
|
1009
993
|
}
|
|
1010
|
-
this.addPendingChangeHelper(id, this.
|
|
994
|
+
this.addPendingChangeHelper(id, this.pendingChangesEnd, serializedInterval);
|
|
1011
995
|
}
|
|
1012
996
|
}
|
|
1013
997
|
|
|
@@ -1028,10 +1012,10 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1028
1012
|
// Change ops always have an ID.
|
|
1029
1013
|
const id: string = serializedInterval.properties[reservedIntervalIdKey];
|
|
1030
1014
|
if (serializedInterval.start !== undefined) {
|
|
1031
|
-
this.removePendingChangeHelper(id, this.
|
|
1015
|
+
this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
1032
1016
|
}
|
|
1033
1017
|
if (serializedInterval.end !== undefined) {
|
|
1034
|
-
this.removePendingChangeHelper(id, this.
|
|
1018
|
+
this.removePendingChangeHelper(id, this.pendingChangesEnd, serializedInterval);
|
|
1035
1019
|
}
|
|
1036
1020
|
}
|
|
1037
1021
|
|
|
@@ -1054,16 +1038,22 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1054
1038
|
}
|
|
1055
1039
|
|
|
1056
1040
|
private hasPendingChangeStart(id: string) {
|
|
1057
|
-
const entries = this.
|
|
1041
|
+
const entries = this.pendingChangesStart?.get(id);
|
|
1058
1042
|
return entries && entries.length !== 0;
|
|
1059
1043
|
}
|
|
1060
1044
|
|
|
1061
1045
|
private hasPendingChangeEnd(id: string) {
|
|
1062
|
-
const entries = this.
|
|
1046
|
+
const entries = this.pendingChangesEnd?.get(id);
|
|
1063
1047
|
return entries && entries.length !== 0;
|
|
1064
1048
|
}
|
|
1065
1049
|
|
|
1050
|
+
/** @deprecated - use ackChange */
|
|
1066
1051
|
public changeInterval(serializedInterval: ISerializedInterval, local: boolean, op: ISequencedDocumentMessage) {
|
|
1052
|
+
return this.ackChange(serializedInterval, local, op);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/** @internal */
|
|
1056
|
+
public ackChange(serializedInterval: ISerializedInterval, local: boolean, op: ISequencedDocumentMessage) {
|
|
1067
1057
|
if (!this.attached) {
|
|
1068
1058
|
throw new Error("Attach must be called before accessing intervals");
|
|
1069
1059
|
}
|
|
@@ -1140,10 +1130,25 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1140
1130
|
});
|
|
1141
1131
|
}
|
|
1142
1132
|
|
|
1133
|
+
/** @deprecated - use ackAdd */
|
|
1143
1134
|
public addInternal(
|
|
1144
1135
|
serializedInterval: ISerializedInterval,
|
|
1145
1136
|
local: boolean,
|
|
1146
1137
|
op: ISequencedDocumentMessage) {
|
|
1138
|
+
return this.ackAdd(serializedInterval, local, op);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/** @internal */
|
|
1142
|
+
public ackAdd(
|
|
1143
|
+
serializedInterval: ISerializedInterval,
|
|
1144
|
+
local: boolean,
|
|
1145
|
+
op: ISequencedDocumentMessage) {
|
|
1146
|
+
if (local) {
|
|
1147
|
+
// Local ops were applied when the message was created and there's no "pending add"
|
|
1148
|
+
// state to bookkeep
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1147
1152
|
if (!this.attached) {
|
|
1148
1153
|
throw new Error("attachSequence must be called");
|
|
1149
1154
|
}
|
|
@@ -1158,14 +1163,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1158
1163
|
op);
|
|
1159
1164
|
|
|
1160
1165
|
if (interval) {
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
// Review: Is this case possible?
|
|
1164
|
-
this.emitter.emit("add", undefined, serializedInterval);
|
|
1165
|
-
} else {
|
|
1166
|
-
if (this.onDeserialize) {
|
|
1167
|
-
this.onDeserialize(interval);
|
|
1168
|
-
}
|
|
1166
|
+
if (this.onDeserialize) {
|
|
1167
|
+
this.onDeserialize(interval);
|
|
1169
1168
|
}
|
|
1170
1169
|
}
|
|
1171
1170
|
|
|
@@ -1174,10 +1173,26 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1174
1173
|
return interval;
|
|
1175
1174
|
}
|
|
1176
1175
|
|
|
1176
|
+
/** @deprecated - use ackDelete */
|
|
1177
1177
|
public deleteInterval(
|
|
1178
1178
|
serializedInterval: ISerializedInterval,
|
|
1179
1179
|
local: boolean,
|
|
1180
1180
|
op: ISequencedDocumentMessage): void {
|
|
1181
|
+
return this.ackDelete(serializedInterval, local, op);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
/** @internal */
|
|
1185
|
+
public ackDelete(
|
|
1186
|
+
serializedInterval: ISerializedInterval,
|
|
1187
|
+
local: boolean,
|
|
1188
|
+
op: ISequencedDocumentMessage): void {
|
|
1189
|
+
if (local) {
|
|
1190
|
+
// Local ops were applied when the message was created and there's no "pending delete"
|
|
1191
|
+
// state to bookkeep: remote operation application takes into account possibility of
|
|
1192
|
+
// locally deleted interval whenever a lookup happens.
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1181
1196
|
if (!this.attached) {
|
|
1182
1197
|
throw new Error("attach must be called prior to deleting intervals");
|
|
1183
1198
|
}
|
package/src/localValues.ts
CHANGED
|
@@ -6,23 +6,19 @@
|
|
|
6
6
|
import { IFluidHandle } from "@fluidframework/core-interfaces";
|
|
7
7
|
import {
|
|
8
8
|
IFluidSerializer,
|
|
9
|
-
ISerializedHandle,
|
|
10
|
-
parseHandles,
|
|
11
9
|
serializeHandles,
|
|
12
|
-
ValueType,
|
|
13
10
|
} from "@fluidframework/shared-object-base";
|
|
14
11
|
import {
|
|
15
12
|
ISerializableValue,
|
|
16
13
|
ISerializedValue,
|
|
17
|
-
IValueOpEmitter,
|
|
18
14
|
IValueOperation,
|
|
19
15
|
IValueType,
|
|
20
|
-
} from "./
|
|
16
|
+
} from "./defaultMapInterfaces";
|
|
21
17
|
|
|
22
18
|
/**
|
|
23
19
|
* A local value to be stored in a container type DDS.
|
|
24
20
|
*/
|
|
25
|
-
export interface ILocalValue {
|
|
21
|
+
export interface ILocalValue<T = any> {
|
|
26
22
|
/**
|
|
27
23
|
* Type indicator of the value stored within.
|
|
28
24
|
*/
|
|
@@ -31,7 +27,7 @@ export interface ILocalValue {
|
|
|
31
27
|
/**
|
|
32
28
|
* The in-memory value stored within.
|
|
33
29
|
*/
|
|
34
|
-
readonly value:
|
|
30
|
+
readonly value: T;
|
|
35
31
|
|
|
36
32
|
/**
|
|
37
33
|
* Retrieve the serialized form of the value stored within.
|
|
@@ -56,57 +52,18 @@ export function makeSerializable(
|
|
|
56
52
|
};
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
/**
|
|
60
|
-
* Manages a contained plain value. May also contain shared object handles.
|
|
61
|
-
*/
|
|
62
|
-
export class PlainLocalValue implements ILocalValue {
|
|
63
|
-
/**
|
|
64
|
-
* Create a new PlainLocalValue.
|
|
65
|
-
* @param value - The value to store, which may contain shared object handles
|
|
66
|
-
*/
|
|
67
|
-
constructor(public readonly value: any) {
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* {@inheritDoc ILocalValue."type"}
|
|
72
|
-
*/
|
|
73
|
-
public get type(): string {
|
|
74
|
-
return ValueType[ValueType.Plain];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* {@inheritDoc ILocalValue.makeSerialized}
|
|
79
|
-
*/
|
|
80
|
-
public makeSerialized(
|
|
81
|
-
serializer: IFluidSerializer,
|
|
82
|
-
bind: IFluidHandle,
|
|
83
|
-
): ISerializedValue {
|
|
84
|
-
// Stringify to convert to the serialized handle values - and then parse in order to create
|
|
85
|
-
// a POJO for the op
|
|
86
|
-
const value = serializeHandles(this.value, serializer, bind);
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
type: this.type,
|
|
90
|
-
value,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
55
|
/**
|
|
96
56
|
* Manages a contained value type.
|
|
97
57
|
*
|
|
98
|
-
* @privateRemarks
|
|
99
|
-
* TODO: Should maybe be a generic
|
|
100
|
-
*
|
|
101
58
|
* @alpha
|
|
102
59
|
*/
|
|
103
|
-
export class ValueTypeLocalValue implements ILocalValue {
|
|
60
|
+
export class ValueTypeLocalValue<T> implements ILocalValue<T> {
|
|
104
61
|
/**
|
|
105
62
|
* Create a new ValueTypeLocalValue.
|
|
106
63
|
* @param value - The instance of the value type stored within
|
|
107
64
|
* @param valueType - The type object of the value type stored within
|
|
108
65
|
*/
|
|
109
|
-
constructor(public readonly value:
|
|
66
|
+
constructor(public readonly value: T, private readonly valueType: IValueType<T>) {
|
|
110
67
|
}
|
|
111
68
|
|
|
112
69
|
/**
|
|
@@ -137,7 +94,7 @@ export class ValueTypeLocalValue implements ILocalValue {
|
|
|
137
94
|
* @param opName - The name of the operation that needs processing
|
|
138
95
|
* @returns The object which can process the given op
|
|
139
96
|
*/
|
|
140
|
-
public getOpHandler(opName: string): IValueOperation<
|
|
97
|
+
public getOpHandler(opName: string): IValueOperation<T> {
|
|
141
98
|
const handler = this.valueType.ops.get(opName);
|
|
142
99
|
if (!handler) {
|
|
143
100
|
throw new Error("Unknown type message");
|
|
@@ -146,108 +103,3 @@ export class ValueTypeLocalValue implements ILocalValue {
|
|
|
146
103
|
return handler;
|
|
147
104
|
}
|
|
148
105
|
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* A LocalValueMaker enables a container type DDS to produce and store local values with minimal awareness of how
|
|
152
|
-
* those objects are stored, serialized, and deserialized.
|
|
153
|
-
*/
|
|
154
|
-
export class LocalValueMaker {
|
|
155
|
-
/**
|
|
156
|
-
* The value types this maker is able to produce.
|
|
157
|
-
*/
|
|
158
|
-
private readonly valueTypes = new Map<string, IValueType<any>>();
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Create a new LocalValueMaker.
|
|
162
|
-
* @param serializer - The serializer to serialize / parse handles.
|
|
163
|
-
*/
|
|
164
|
-
constructor(private readonly serializer: IFluidSerializer) {
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Register a value type this maker will be able to produce.
|
|
169
|
-
* @param type - The value type to register
|
|
170
|
-
* @alpha
|
|
171
|
-
*/
|
|
172
|
-
public registerValueType<T>(type: IValueType<T>) {
|
|
173
|
-
this.valueTypes.set(type.name, type);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Create a new local value from an incoming serialized value.
|
|
178
|
-
* @param serializable - The serializable value to make local
|
|
179
|
-
*/
|
|
180
|
-
public fromSerializable(serializable: ISerializableValue): ILocalValue {
|
|
181
|
-
// Migrate from old shared value to handles
|
|
182
|
-
if (serializable.type === ValueType[ValueType.Shared]) {
|
|
183
|
-
serializable.type = ValueType[ValueType.Plain];
|
|
184
|
-
const handle: ISerializedHandle = {
|
|
185
|
-
type: "__fluid_handle__",
|
|
186
|
-
url: serializable.value as string,
|
|
187
|
-
};
|
|
188
|
-
serializable.value = handle;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const translatedValue = parseHandles(serializable.value, this.serializer);
|
|
192
|
-
|
|
193
|
-
return new PlainLocalValue(translatedValue);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Create a new local value from an incoming serialized value for value type
|
|
198
|
-
* @param serializable - The serializable value to make local
|
|
199
|
-
* @param emitter - The value op emitter, if the serializable is a value type
|
|
200
|
-
*/
|
|
201
|
-
public fromSerializableValueType(serializable: ISerializableValue, emitter: IValueOpEmitter): ILocalValue {
|
|
202
|
-
if (this.valueTypes.has(serializable.type)) {
|
|
203
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
204
|
-
const valueType = this.valueTypes.get(serializable.type)!;
|
|
205
|
-
|
|
206
|
-
serializable.value = parseHandles(serializable.value, this.serializer);
|
|
207
|
-
|
|
208
|
-
const localValue = valueType.factory.load(emitter, serializable.value);
|
|
209
|
-
return new ValueTypeLocalValue(localValue, valueType);
|
|
210
|
-
} else {
|
|
211
|
-
throw new Error(`Unknown value type "${serializable.type}"`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Create a new local value containing a given plain object.
|
|
217
|
-
* @param value - The value to store
|
|
218
|
-
* @returns An ILocalValue containing the value
|
|
219
|
-
*/
|
|
220
|
-
public fromInMemory(value: any): ILocalValue {
|
|
221
|
-
return new PlainLocalValue(value);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Create a new local value containing a value type.
|
|
226
|
-
* @param type - The type of the value type to create
|
|
227
|
-
* @param emitter - The IValueOpEmitter object that the new value type will use to emit ops
|
|
228
|
-
* @param params - The initialization arguments for the value type
|
|
229
|
-
* @returns An ILocalValue containing the new value type
|
|
230
|
-
* @alpha
|
|
231
|
-
*/
|
|
232
|
-
public makeValueType(type: string, emitter: IValueOpEmitter, params: any): ILocalValue {
|
|
233
|
-
const valueType = this.loadValueType(params, type, emitter);
|
|
234
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
235
|
-
return new ValueTypeLocalValue(valueType, this.valueTypes.get(type)!);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Create a new value type.
|
|
240
|
-
* @param params - The initialization arguments for the value type
|
|
241
|
-
* @param type - The type of value type to create
|
|
242
|
-
* @param emitter - The IValueOpEmitter object that the new value type will use to emit ops
|
|
243
|
-
* @returns The new value type
|
|
244
|
-
* @alpha
|
|
245
|
-
*/
|
|
246
|
-
private loadValueType(params: any, type: string, emitter: IValueOpEmitter): any {
|
|
247
|
-
const valueType = this.valueTypes.get(type);
|
|
248
|
-
if (!valueType) {
|
|
249
|
-
throw new Error(`Unknown type '${type}' specified`);
|
|
250
|
-
}
|
|
251
|
-
return valueType.factory.load(emitter, params);
|
|
252
|
-
}
|
|
253
|
-
}
|
package/src/packageVersion.ts
CHANGED
package/src/sequence.ts
CHANGED
|
@@ -55,8 +55,8 @@ import {
|
|
|
55
55
|
SequenceInterval,
|
|
56
56
|
SequenceIntervalCollectionValueType,
|
|
57
57
|
} from "./intervalCollection";
|
|
58
|
-
import {
|
|
59
|
-
import { IValueChanged } from "./
|
|
58
|
+
import { IMapMessageLocalMetadata, DefaultMap } from "./defaultMap";
|
|
59
|
+
import { IValueChanged } from "./defaultMapInterfaces";
|
|
60
60
|
import { SequenceDeltaEvent, SequenceMaintenanceEvent } from "./sequenceDeltaEvent";
|
|
61
61
|
import { ISharedIntervalCollection } from "./sharedIntervalCollection";
|
|
62
62
|
|
|
@@ -166,7 +166,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
166
166
|
private readonly loadedDeferredIncomingOps: ISequencedDocumentMessage[] = [];
|
|
167
167
|
|
|
168
168
|
private messagesSinceMSNChange: ISequencedDocumentMessage[] = [];
|
|
169
|
-
private readonly
|
|
169
|
+
private readonly intervalCollections: DefaultMap<IntervalCollection<SequenceInterval>>;
|
|
170
170
|
constructor(
|
|
171
171
|
private readonly dataStoreRuntime: IFluidDataStoreRuntime,
|
|
172
172
|
public id: string,
|
|
@@ -220,12 +220,12 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
220
220
|
}
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
-
this.
|
|
223
|
+
this.intervalCollections = new DefaultMap(
|
|
224
224
|
this.serializer,
|
|
225
225
|
this.handle,
|
|
226
226
|
(op, localOpMetadata) => this.submitLocalMessage(op, localOpMetadata),
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
new SequenceIntervalCollectionValueType(),
|
|
228
|
+
);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
/**
|
|
@@ -435,25 +435,19 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
435
435
|
}
|
|
436
436
|
}
|
|
437
437
|
|
|
438
|
+
/**
|
|
439
|
+
* @deprecated - IntervalCollections are created on a first-write wins basis, and concurrent creates
|
|
440
|
+
* are supported. Use `getIntervalCollection` instead.
|
|
441
|
+
*/
|
|
438
442
|
public async waitIntervalCollection(
|
|
439
443
|
label: string,
|
|
440
444
|
): Promise<IntervalCollection<SequenceInterval>> {
|
|
441
|
-
return this.
|
|
442
|
-
this.getIntervalCollectionPath(label));
|
|
445
|
+
return this.intervalCollections.get(this.getIntervalCollectionPath(label));
|
|
443
446
|
}
|
|
444
447
|
|
|
445
|
-
// TODO: fix race condition on creation by putting type on every operation
|
|
446
448
|
public getIntervalCollection(label: string): IntervalCollection<SequenceInterval> {
|
|
447
449
|
const labelPath = this.getIntervalCollectionPath(label);
|
|
448
|
-
|
|
449
|
-
this.intervalMapKernel.createValueType(
|
|
450
|
-
labelPath,
|
|
451
|
-
SequenceIntervalCollectionValueType.Name,
|
|
452
|
-
undefined);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
const sharedCollection =
|
|
456
|
-
this.intervalMapKernel.get<IntervalCollection<SequenceInterval>>(labelPath);
|
|
450
|
+
const sharedCollection = this.intervalCollections.get(labelPath);
|
|
457
451
|
return sharedCollection;
|
|
458
452
|
}
|
|
459
453
|
|
|
@@ -466,7 +460,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
466
460
|
* ...
|
|
467
461
|
*/
|
|
468
462
|
public getIntervalCollectionLabels(): IterableIterator<string> {
|
|
469
|
-
return this.
|
|
463
|
+
return this.intervalCollections.keys();
|
|
470
464
|
}
|
|
471
465
|
|
|
472
466
|
protected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats {
|
|
@@ -474,8 +468,8 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
474
468
|
|
|
475
469
|
// conditionally write the interval collection blob
|
|
476
470
|
// only if it has entries
|
|
477
|
-
if (this.
|
|
478
|
-
builder.addBlob(snapshotFileName, this.
|
|
471
|
+
if (this.intervalCollections.size > 0) {
|
|
472
|
+
builder.addBlob(snapshotFileName, this.intervalCollections.serialize(serializer));
|
|
479
473
|
}
|
|
480
474
|
|
|
481
475
|
builder.addWithStats(contentPath, this.summarizeMergeTree(serializer));
|
|
@@ -488,8 +482,8 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
488
482
|
* All the IFluidHandle's represent routes to other objects.
|
|
489
483
|
*/
|
|
490
484
|
protected processGCDataCore(serializer: SummarySerializer) {
|
|
491
|
-
if (this.
|
|
492
|
-
this.
|
|
485
|
+
if (this.intervalCollections.size > 0) {
|
|
486
|
+
this.intervalCollections.serialize(serializer);
|
|
493
487
|
}
|
|
494
488
|
|
|
495
489
|
this.client.serializeGCData(this.handle, serializer);
|
|
@@ -528,7 +522,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
528
522
|
protected onDisconnect() {}
|
|
529
523
|
|
|
530
524
|
protected reSubmitCore(content: any, localOpMetadata: unknown) {
|
|
531
|
-
if (!this.
|
|
525
|
+
if (!this.intervalCollections.trySubmitMessage(content, localOpMetadata as IMapMessageLocalMetadata)) {
|
|
532
526
|
this.submitSequenceMessage(
|
|
533
527
|
this.client.regeneratePendingOp(
|
|
534
528
|
content as IMergeTreeOp,
|
|
@@ -543,7 +537,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
543
537
|
if (await storage.contains(snapshotFileName)) {
|
|
544
538
|
const blob = await storage.readBlob(snapshotFileName);
|
|
545
539
|
const header = bufferToString(blob, "utf8");
|
|
546
|
-
this.
|
|
540
|
+
this.intervalCollections.populate(header);
|
|
547
541
|
}
|
|
548
542
|
|
|
549
543
|
try {
|
|
@@ -604,7 +598,12 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
604
598
|
} else {
|
|
605
599
|
assert(message.type === MessageType.Operation, 0x073 /* "Sequence message not operation" */);
|
|
606
600
|
|
|
607
|
-
const handled = this.
|
|
601
|
+
const handled = this.intervalCollections.tryProcessMessage(
|
|
602
|
+
message.contents,
|
|
603
|
+
local,
|
|
604
|
+
message,
|
|
605
|
+
localOpMetadata,
|
|
606
|
+
);
|
|
608
607
|
|
|
609
608
|
if (!handled) {
|
|
610
609
|
this.processMergeTreeMsg(message, local);
|
|
@@ -728,18 +727,18 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
728
727
|
|
|
729
728
|
private initializeIntervalCollections() {
|
|
730
729
|
// Listen and initialize new SharedIntervalCollections
|
|
731
|
-
this.
|
|
732
|
-
const intervalCollection = this.
|
|
730
|
+
this.intervalCollections.eventEmitter.on("create", ({ key, previousValue }: IValueChanged, local: boolean) => {
|
|
731
|
+
const intervalCollection = this.intervalCollections.get(key);
|
|
733
732
|
if (!intervalCollection.attached) {
|
|
734
|
-
intervalCollection.attachGraph(this.client,
|
|
733
|
+
intervalCollection.attachGraph(this.client, key);
|
|
735
734
|
}
|
|
736
|
-
assert(
|
|
737
|
-
this.emit("createIntervalCollection",
|
|
735
|
+
assert(previousValue === undefined, 0x2c1 /* "Creating an interval collection that already exists?" */);
|
|
736
|
+
this.emit("createIntervalCollection", key, local, this);
|
|
738
737
|
});
|
|
739
738
|
|
|
740
739
|
// Initialize existing SharedIntervalCollections
|
|
741
|
-
for (const key of this.
|
|
742
|
-
const intervalCollection = this.
|
|
740
|
+
for (const key of this.intervalCollections.keys()) {
|
|
741
|
+
const intervalCollection = this.intervalCollections.get(key);
|
|
743
742
|
intervalCollection.attachGraph(this.client, key);
|
|
744
743
|
}
|
|
745
744
|
}
|