@fluidframework/map 2.0.0-rc.1.0.6 → 2.0.0-rc.2.0.1
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 → .eslintrc.cjs} +10 -1
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +11 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/map.api.md +14 -57
- package/dist/directory.d.ts +10 -50
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +76 -164
- package/dist/directory.js.map +1 -1
- package/dist/index.d.ts +45 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -8
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/internalInterfaces.d.ts +2 -2
- package/dist/internalInterfaces.d.ts.map +1 -1
- package/dist/internalInterfaces.js.map +1 -1
- package/dist/localValues.d.ts +3 -5
- package/dist/localValues.d.ts.map +1 -1
- package/dist/localValues.js +9 -8
- package/dist/localValues.js.map +1 -1
- package/dist/map-alpha.d.ts +31 -116
- package/dist/map-beta.d.ts +24 -105
- package/dist/map-public.d.ts +24 -105
- package/dist/map-untrimmed.d.ts +31 -116
- package/dist/map.d.ts +4 -23
- package/dist/map.d.ts.map +1 -1
- package/dist/map.js +6 -29
- package/dist/map.js.map +1 -1
- package/dist/mapKernel.d.ts +3 -4
- package/dist/mapKernel.d.ts.map +1 -1
- package/dist/mapKernel.js +30 -35
- package/dist/mapKernel.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{directory.d.mts → directory.d.ts} +11 -51
- package/lib/directory.d.ts.map +1 -0
- package/lib/{directory.mjs → directory.js} +77 -165
- package/lib/directory.js.map +1 -0
- package/lib/index.d.ts +61 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +55 -0
- package/lib/index.js.map +1 -0
- package/lib/{interfaces.d.mts → interfaces.d.ts} +1 -1
- package/lib/interfaces.d.ts.map +1 -0
- package/lib/{interfaces.mjs → interfaces.js} +1 -1
- package/lib/interfaces.js.map +1 -0
- package/lib/{internalInterfaces.d.mts → internalInterfaces.d.ts} +3 -3
- package/lib/internalInterfaces.d.ts.map +1 -0
- package/lib/{internalInterfaces.mjs → internalInterfaces.js} +1 -1
- package/lib/internalInterfaces.js.map +1 -0
- package/lib/{localValues.d.mts → localValues.d.ts} +4 -6
- package/lib/localValues.d.ts.map +1 -0
- package/lib/{localValues.mjs → localValues.js} +10 -9
- package/lib/localValues.js.map +1 -0
- package/lib/{map-alpha.d.mts → map-alpha.d.ts} +43 -116
- package/lib/{map-beta.d.mts → map-beta.d.ts} +36 -105
- package/lib/{map-public.d.mts → map-public.d.ts} +36 -105
- package/lib/{map-untrimmed.d.mts → map-untrimmed.d.ts} +43 -116
- package/lib/{map.d.mts → map.d.ts} +5 -24
- package/lib/map.d.ts.map +1 -0
- package/lib/{map.mjs → map.js} +5 -28
- package/lib/map.js.map +1 -0
- package/lib/{mapKernel.d.mts → mapKernel.d.ts} +4 -5
- package/lib/mapKernel.d.ts.map +1 -0
- package/lib/{mapKernel.mjs → mapKernel.js} +32 -37
- package/lib/mapKernel.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/test/memory/directory.spec.js +71 -0
- package/lib/test/memory/directory.spec.js.map +1 -0
- package/lib/test/memory/map.spec.js +71 -0
- package/lib/test/memory/map.spec.js.map +1 -0
- package/lib/test/mocha/directory.order.spec.js +422 -0
- package/lib/test/mocha/directory.order.spec.js.map +1 -0
- package/lib/test/mocha/directory.snapshot.spec.js +111 -0
- package/lib/test/mocha/directory.snapshot.spec.js.map +1 -0
- package/lib/test/mocha/directory.spec.js +1406 -0
- package/lib/test/mocha/directory.spec.js.map +1 -0
- package/lib/test/mocha/directoryEquivalenceUtils.js +36 -0
- package/lib/test/mocha/directoryEquivalenceUtils.js.map +1 -0
- package/lib/test/mocha/directoryFuzzTests.spec.js +337 -0
- package/lib/test/mocha/directoryFuzzTests.spec.js.map +1 -0
- package/lib/test/mocha/dirname.cjs +16 -0
- package/lib/test/mocha/dirname.cjs.map +1 -0
- package/lib/test/mocha/map.fuzz.spec.js +114 -0
- package/lib/test/mocha/map.fuzz.spec.js.map +1 -0
- package/lib/test/mocha/map.spec.js +685 -0
- package/lib/test/mocha/map.spec.js.map +1 -0
- package/lib/test/mocha/rebasing.spec.js +158 -0
- package/lib/test/mocha/rebasing.spec.js.map +1 -0
- package/lib/test/mocha/reconnection.spec.js +327 -0
- package/lib/test/mocha/reconnection.spec.js.map +1 -0
- package/lib/test/types/validateMapPrevious.generated.js +66 -0
- package/lib/test/types/validateMapPrevious.generated.js.map +1 -0
- package/package.json +55 -52
- package/src/directory.ts +122 -217
- package/src/index.ts +57 -4
- package/src/interfaces.ts +2 -2
- package/src/internalInterfaces.ts +2 -2
- package/src/localValues.ts +14 -9
- package/src/map.ts +7 -32
- package/src/mapKernel.ts +40 -42
- package/src/packageVersion.ts +1 -1
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/lib/directory.d.mts.map +0 -1
- package/lib/directory.mjs.map +0 -1
- package/lib/index.d.mts +0 -9
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -8
- package/lib/index.mjs.map +0 -1
- package/lib/interfaces.d.mts.map +0 -1
- package/lib/interfaces.mjs.map +0 -1
- package/lib/internalInterfaces.d.mts.map +0 -1
- package/lib/internalInterfaces.mjs.map +0 -1
- package/lib/localValues.d.mts.map +0 -1
- package/lib/localValues.mjs.map +0 -1
- package/lib/map.d.mts.map +0 -1
- package/lib/map.mjs.map +0 -1
- package/lib/mapKernel.d.mts.map +0 -1
- package/lib/mapKernel.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
package/src/directory.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert } from "@fluidframework/core-utils";
|
|
6
|
+
import { assert, unreachableCase } from "@fluidframework/core-utils";
|
|
7
7
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
8
8
|
import { ITelemetryLoggerExt, UsageError } from "@fluidframework/telemetry-utils";
|
|
9
9
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
@@ -16,7 +16,12 @@ import {
|
|
|
16
16
|
IChannelFactory,
|
|
17
17
|
} from "@fluidframework/datastore-definitions";
|
|
18
18
|
import { ISummaryTreeWithStats, ITelemetryContext } from "@fluidframework/runtime-definitions";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
IFluidSerializer,
|
|
21
|
+
SharedObject,
|
|
22
|
+
ValueType,
|
|
23
|
+
parseHandles,
|
|
24
|
+
} from "@fluidframework/shared-object-base";
|
|
20
25
|
import { SummaryTreeBuilder } from "@fluidframework/runtime-utils";
|
|
21
26
|
import path from "path-browserify";
|
|
22
27
|
import { RedBlackTree } from "@fluidframework/merge-tree";
|
|
@@ -30,9 +35,9 @@ import {
|
|
|
30
35
|
ISharedDirectory,
|
|
31
36
|
ISharedDirectoryEvents,
|
|
32
37
|
IValueChanged,
|
|
33
|
-
} from "./interfaces";
|
|
34
|
-
import { ILocalValue, LocalValueMaker, makeSerializable } from "./localValues";
|
|
35
|
-
import { pkgVersion } from "./packageVersion";
|
|
38
|
+
} from "./interfaces.js";
|
|
39
|
+
import { ILocalValue, LocalValueMaker, makeSerializable } from "./localValues.js";
|
|
40
|
+
import { pkgVersion } from "./packageVersion.js";
|
|
36
41
|
|
|
37
42
|
// We use path-browserify since this code can run safely on the server or the browser.
|
|
38
43
|
// We standardize on using posix slashes everywhere.
|
|
@@ -65,8 +70,6 @@ interface IDirectoryMessageHandler {
|
|
|
65
70
|
* @param localOpMetadata - The metadata to be submitted with the message.
|
|
66
71
|
*/
|
|
67
72
|
submit(op: IDirectoryOperation, localOpMetadata: unknown): void;
|
|
68
|
-
|
|
69
|
-
applyStashedOp(op: IDirectoryOperation): unknown;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
/**
|
|
@@ -271,7 +274,7 @@ export interface IDirectoryNewStorageFormat {
|
|
|
271
274
|
* @sealed
|
|
272
275
|
* @alpha
|
|
273
276
|
*/
|
|
274
|
-
export class DirectoryFactory implements IChannelFactory {
|
|
277
|
+
export class DirectoryFactory implements IChannelFactory<ISharedDirectory> {
|
|
275
278
|
/**
|
|
276
279
|
* {@inheritDoc @fluidframework/datastore-definitions#IChannelFactory."type"}
|
|
277
280
|
*/
|
|
@@ -346,25 +349,25 @@ export class DirectoryFactory implements IChannelFactory {
|
|
|
346
349
|
* 4. A 'seq' value of zero indicates that the subdirectory was created in detached state, and it is considered acknowledged for the
|
|
347
350
|
* purpose of ordering.
|
|
348
351
|
*/
|
|
349
|
-
const seqDataComparator = (a: SequenceData, b: SequenceData) => {
|
|
352
|
+
const seqDataComparator = (a: SequenceData, b: SequenceData): number => {
|
|
350
353
|
if (isAcknowledgedOrDetached(a)) {
|
|
351
354
|
if (isAcknowledgedOrDetached(b)) {
|
|
352
355
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
353
|
-
return a.seq
|
|
356
|
+
return a.seq === b.seq ? a.clientSeq! - b.clientSeq! : a.seq - b.seq;
|
|
354
357
|
} else {
|
|
355
358
|
return -1;
|
|
356
359
|
}
|
|
357
360
|
} else {
|
|
358
|
-
if (
|
|
359
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
360
|
-
return a.seq !== b.seq ? a.seq - b.seq : a.clientSeq! - b.clientSeq!;
|
|
361
|
-
} else {
|
|
361
|
+
if (isAcknowledgedOrDetached(b)) {
|
|
362
362
|
return 1;
|
|
363
|
+
} else {
|
|
364
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
365
|
+
return a.seq === b.seq ? a.clientSeq! - b.clientSeq! : a.seq - b.seq;
|
|
363
366
|
}
|
|
364
367
|
}
|
|
365
368
|
};
|
|
366
369
|
|
|
367
|
-
function isAcknowledgedOrDetached(seqData: SequenceData) {
|
|
370
|
+
function isAcknowledgedOrDetached(seqData: SequenceData): boolean {
|
|
368
371
|
return seqData.seq >= 0;
|
|
369
372
|
}
|
|
370
373
|
|
|
@@ -464,8 +467,8 @@ export class SharedDirectory
|
|
|
464
467
|
* @param id - Optional name of the shared directory
|
|
465
468
|
* @returns Newly create shared directory (but not attached yet)
|
|
466
469
|
*/
|
|
467
|
-
public static create(runtime: IFluidDataStoreRuntime, id?: string):
|
|
468
|
-
return runtime.createChannel(id, DirectoryFactory.Type) as
|
|
470
|
+
public static create(runtime: IFluidDataStoreRuntime, id?: string): ISharedDirectory {
|
|
471
|
+
return runtime.createChannel(id, DirectoryFactory.Type) as ISharedDirectory;
|
|
469
472
|
}
|
|
470
473
|
|
|
471
474
|
/**
|
|
@@ -473,7 +476,7 @@ export class SharedDirectory
|
|
|
473
476
|
*
|
|
474
477
|
* @returns A factory that creates and load SharedDirectory
|
|
475
478
|
*/
|
|
476
|
-
public static getFactory(): IChannelFactory {
|
|
479
|
+
public static getFactory(): IChannelFactory<ISharedDirectory> {
|
|
477
480
|
return new DirectoryFactory();
|
|
478
481
|
}
|
|
479
482
|
|
|
@@ -523,7 +526,7 @@ export class SharedDirectory
|
|
|
523
526
|
attributes: IChannelAttributes,
|
|
524
527
|
) {
|
|
525
528
|
super(id, runtime, attributes, "fluid_directory_");
|
|
526
|
-
this.localValueMaker = new LocalValueMaker(
|
|
529
|
+
this.localValueMaker = new LocalValueMaker();
|
|
527
530
|
this.setMessageHandlers();
|
|
528
531
|
// Mirror the containedValueChanged op on the SharedDirectory
|
|
529
532
|
this.root.on("containedValueChanged", (changed: IValueChanged, local: boolean) => {
|
|
@@ -808,9 +811,9 @@ export class SharedDirectory
|
|
|
808
811
|
}
|
|
809
812
|
newSubDir = new SubDirectory(
|
|
810
813
|
seqData,
|
|
811
|
-
createInfo
|
|
812
|
-
? new Set
|
|
813
|
-
: new Set(),
|
|
814
|
+
createInfo === undefined
|
|
815
|
+
? new Set()
|
|
816
|
+
: new Set<string>(createInfo.ccIds),
|
|
814
817
|
this,
|
|
815
818
|
this.runtime,
|
|
816
819
|
this.serializer,
|
|
@@ -832,7 +835,8 @@ export class SharedDirectory
|
|
|
832
835
|
const localValue = this.makeLocal(
|
|
833
836
|
key,
|
|
834
837
|
currentSubDir.absolutePath,
|
|
835
|
-
|
|
838
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
839
|
+
parseHandles(serializable, this.serializer),
|
|
836
840
|
);
|
|
837
841
|
currentSubDir.populateStorage(key, localValue);
|
|
838
842
|
}
|
|
@@ -896,7 +900,7 @@ export class SharedDirectory
|
|
|
896
900
|
serializable.type === ValueType[ValueType.Shared],
|
|
897
901
|
0x1e4 /* "Unexpected serializable type" */,
|
|
898
902
|
);
|
|
899
|
-
return this.localValueMaker.fromSerializable(serializable);
|
|
903
|
+
return this.localValueMaker.fromSerializable(serializable, this.serializer, this.handle);
|
|
900
904
|
}
|
|
901
905
|
|
|
902
906
|
/**
|
|
@@ -950,12 +954,6 @@ export class SharedDirectory
|
|
|
950
954
|
subdir.resubmitClearMessage(op, localOpMetadata);
|
|
951
955
|
}
|
|
952
956
|
},
|
|
953
|
-
applyStashedOp: (op: IDirectoryClearOperation): IClearLocalOpMetadata | undefined => {
|
|
954
|
-
const subdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
955
|
-
if (subdir) {
|
|
956
|
-
return subdir.applyStashedClearMessage(op);
|
|
957
|
-
}
|
|
958
|
-
},
|
|
959
957
|
});
|
|
960
958
|
this.messageHandlers.set("delete", {
|
|
961
959
|
process: (
|
|
@@ -977,14 +975,6 @@ export class SharedDirectory
|
|
|
977
975
|
subdir.resubmitKeyMessage(op, localOpMetadata);
|
|
978
976
|
}
|
|
979
977
|
},
|
|
980
|
-
applyStashedOp: (
|
|
981
|
-
op: IDirectoryDeleteOperation,
|
|
982
|
-
): IKeyEditLocalOpMetadata | undefined => {
|
|
983
|
-
const subdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
984
|
-
if (subdir) {
|
|
985
|
-
return subdir.applyStashedDeleteMessage(op);
|
|
986
|
-
}
|
|
987
|
-
},
|
|
988
978
|
});
|
|
989
979
|
this.messageHandlers.set("set", {
|
|
990
980
|
process: (
|
|
@@ -1007,13 +997,6 @@ export class SharedDirectory
|
|
|
1007
997
|
subdir.resubmitKeyMessage(op, localOpMetadata);
|
|
1008
998
|
}
|
|
1009
999
|
},
|
|
1010
|
-
applyStashedOp: (op: IDirectorySetOperation): IKeyEditLocalOpMetadata | undefined => {
|
|
1011
|
-
const subdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
1012
|
-
if (subdir) {
|
|
1013
|
-
const context = this.makeLocal(op.key, op.path, op.value);
|
|
1014
|
-
return subdir.applyStashedSetMessage(op, context);
|
|
1015
|
-
}
|
|
1016
|
-
},
|
|
1017
1000
|
});
|
|
1018
1001
|
|
|
1019
1002
|
this.messageHandlers.set("createSubDirectory", {
|
|
@@ -1037,14 +1020,6 @@ export class SharedDirectory
|
|
|
1037
1020
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
1038
1021
|
}
|
|
1039
1022
|
},
|
|
1040
|
-
applyStashedOp: (
|
|
1041
|
-
op: IDirectoryCreateSubDirectoryOperation,
|
|
1042
|
-
): ICreateSubDirLocalOpMetadata | undefined => {
|
|
1043
|
-
const parentSubdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
1044
|
-
if (parentSubdir) {
|
|
1045
|
-
return parentSubdir.applyStashedCreateSubDirMessage(op);
|
|
1046
|
-
}
|
|
1047
|
-
},
|
|
1048
1023
|
});
|
|
1049
1024
|
|
|
1050
1025
|
this.messageHandlers.set("deleteSubDirectory", {
|
|
@@ -1068,26 +1043,47 @@ export class SharedDirectory
|
|
|
1068
1043
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
1069
1044
|
}
|
|
1070
1045
|
},
|
|
1071
|
-
applyStashedOp: (
|
|
1072
|
-
op: IDirectoryDeleteSubDirectoryOperation,
|
|
1073
|
-
): IDeleteSubDirLocalOpMetadata | undefined => {
|
|
1074
|
-
const parentSubdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
1075
|
-
if (parentSubdir) {
|
|
1076
|
-
return parentSubdir.applyStashedDeleteSubDirMessage(op);
|
|
1077
|
-
}
|
|
1078
|
-
},
|
|
1079
1046
|
});
|
|
1080
1047
|
}
|
|
1081
1048
|
|
|
1082
1049
|
/**
|
|
1083
1050
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
1084
1051
|
*/
|
|
1085
|
-
protected applyStashedOp(op: unknown):
|
|
1086
|
-
const
|
|
1087
|
-
|
|
1088
|
-
|
|
1052
|
+
protected applyStashedOp(op: unknown): void {
|
|
1053
|
+
const directoryOp = op as IDirectoryOperation;
|
|
1054
|
+
const dir = this.getWorkingDirectory(directoryOp.path);
|
|
1055
|
+
switch (directoryOp.type) {
|
|
1056
|
+
case "clear": {
|
|
1057
|
+
dir?.clear();
|
|
1058
|
+
break;
|
|
1059
|
+
}
|
|
1060
|
+
case "createSubDirectory": {
|
|
1061
|
+
dir?.createSubDirectory(directoryOp.subdirName);
|
|
1062
|
+
break;
|
|
1063
|
+
}
|
|
1064
|
+
case "delete": {
|
|
1065
|
+
dir?.delete(directoryOp.key);
|
|
1066
|
+
break;
|
|
1067
|
+
}
|
|
1068
|
+
case "deleteSubDirectory": {
|
|
1069
|
+
dir?.deleteSubDirectory(directoryOp.subdirName);
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
case "set": {
|
|
1073
|
+
dir?.set(
|
|
1074
|
+
directoryOp.key,
|
|
1075
|
+
this.localValueMaker.fromSerializable(
|
|
1076
|
+
directoryOp.value,
|
|
1077
|
+
this.serializer,
|
|
1078
|
+
this.handle,
|
|
1079
|
+
).value,
|
|
1080
|
+
);
|
|
1081
|
+
break;
|
|
1082
|
+
}
|
|
1083
|
+
default: {
|
|
1084
|
+
unreachableCase(directoryOp);
|
|
1085
|
+
}
|
|
1089
1086
|
}
|
|
1090
|
-
return handler.applyStashedOp(op as IDirectoryOperation);
|
|
1091
1087
|
}
|
|
1092
1088
|
|
|
1093
1089
|
private serializeDirectory(
|
|
@@ -1221,6 +1217,7 @@ function isDirectoryLocalOpMetadata(metadata: any): metadata is DirectoryLocalOp
|
|
|
1221
1217
|
|
|
1222
1218
|
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
1223
1219
|
|
|
1220
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
1224
1221
|
function assertNonNullClientId(clientId: string | null): asserts clientId is string {
|
|
1225
1222
|
assert(clientId !== null, 0x6af /* client id should never be null */);
|
|
1226
1223
|
}
|
|
@@ -1451,13 +1448,15 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1451
1448
|
}
|
|
1452
1449
|
|
|
1453
1450
|
/**
|
|
1454
|
-
*
|
|
1451
|
+
* Gets the Sequence Data which should be used for local changes.
|
|
1452
|
+
*
|
|
1455
1453
|
* @remarks While detached, 0 is used rather than -1 to represent a change which should be universally known (as opposed to known
|
|
1456
1454
|
* only by the local client). This ensures that if the directory is later attached, none of its data needs to be updated (the values
|
|
1457
1455
|
* last set while detached will now be known to any new client, until they are changed).
|
|
1458
1456
|
*
|
|
1459
1457
|
* The client sequence number is incremented by 1 for maintaining the internal order of locally created subdirectories
|
|
1460
|
-
*
|
|
1458
|
+
*
|
|
1459
|
+
* @privateRemarks TODO: Convert these conventions to named constants. The semantics used here match those for merge-tree.
|
|
1461
1460
|
*/
|
|
1462
1461
|
private getLocalSeq(): SequenceData {
|
|
1463
1462
|
return this.directory.isAttached()
|
|
@@ -1541,15 +1540,19 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1541
1540
|
const entriesIterator = {
|
|
1542
1541
|
index: 0,
|
|
1543
1542
|
dirs: this._subdirectories,
|
|
1544
|
-
next(): IteratorResult<[string,
|
|
1543
|
+
next(): IteratorResult<[string, IDirectory]> {
|
|
1545
1544
|
if (this.index < subdirNames.length) {
|
|
1546
1545
|
const subdirName = subdirNames[this.index++];
|
|
1547
1546
|
const subdir = this.dirs.get(subdirName);
|
|
1547
|
+
assert(
|
|
1548
|
+
subdir !== undefined,
|
|
1549
|
+
0x8ac /* Could not find expected sub-directory. */,
|
|
1550
|
+
);
|
|
1548
1551
|
return { value: [subdirName, subdir], done: false };
|
|
1549
1552
|
}
|
|
1550
1553
|
return { value: undefined, done: true };
|
|
1551
1554
|
},
|
|
1552
|
-
[Symbol.iterator](): IterableIterator<[string,
|
|
1555
|
+
[Symbol.iterator](): IterableIterator<[string, IDirectory]> {
|
|
1553
1556
|
return this;
|
|
1554
1557
|
},
|
|
1555
1558
|
};
|
|
@@ -1712,7 +1715,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1712
1715
|
* @param local - Whether the message originated from the local client
|
|
1713
1716
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1714
1717
|
* For messages from a remote client, this will be undefined.
|
|
1715
|
-
* @internal
|
|
1716
1718
|
*/
|
|
1717
1719
|
public processClearMessage(
|
|
1718
1720
|
msg: ISequencedDocumentMessage,
|
|
@@ -1739,25 +1741,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1739
1741
|
this.clearExceptPendingKeys(false);
|
|
1740
1742
|
}
|
|
1741
1743
|
|
|
1742
|
-
/**
|
|
1743
|
-
* Apply clear operation locally and generate metadata
|
|
1744
|
-
* @param op - Op to apply
|
|
1745
|
-
* @returns metadata generated for stahed op
|
|
1746
|
-
*/
|
|
1747
|
-
public applyStashedClearMessage(op: IDirectoryClearOperation): IClearLocalOpMetadata {
|
|
1748
|
-
this.throwIfDisposed();
|
|
1749
|
-
const previousValue = new Map<string, ILocalValue>(this._storage);
|
|
1750
|
-
this.clearExceptPendingKeys(true);
|
|
1751
|
-
const pendingMsgId = ++this.pendingMessageId;
|
|
1752
|
-
this.pendingClearMessageIds.push(pendingMsgId);
|
|
1753
|
-
const metadata: IClearLocalOpMetadata = {
|
|
1754
|
-
type: "clear",
|
|
1755
|
-
pendingMessageId: pendingMsgId,
|
|
1756
|
-
previousStorage: previousValue,
|
|
1757
|
-
};
|
|
1758
|
-
return metadata;
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
1744
|
/**
|
|
1762
1745
|
* Process a delete operation.
|
|
1763
1746
|
* @param msg - The message from the server to apply.
|
|
@@ -1765,7 +1748,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1765
1748
|
* @param local - Whether the message originated from the local client
|
|
1766
1749
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1767
1750
|
* For messages from a remote client, this will be undefined.
|
|
1768
|
-
* @internal
|
|
1769
1751
|
*/
|
|
1770
1752
|
public processDeleteMessage(
|
|
1771
1753
|
msg: ISequencedDocumentMessage,
|
|
@@ -1785,23 +1767,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1785
1767
|
this.deleteCore(op.key, local);
|
|
1786
1768
|
}
|
|
1787
1769
|
|
|
1788
|
-
/**
|
|
1789
|
-
* Apply delete operation locally and generate metadata
|
|
1790
|
-
* @param op - Op to apply
|
|
1791
|
-
* @returns metadata generated for stahed op
|
|
1792
|
-
*/
|
|
1793
|
-
public applyStashedDeleteMessage(op: IDirectoryDeleteOperation): IKeyEditLocalOpMetadata {
|
|
1794
|
-
this.throwIfDisposed();
|
|
1795
|
-
const previousValue = this.deleteCore(op.key, true);
|
|
1796
|
-
const pendingMessageId = this.getKeyMessageId(op);
|
|
1797
|
-
const localMetadata: IKeyEditLocalOpMetadata = {
|
|
1798
|
-
type: "edit",
|
|
1799
|
-
pendingMessageId,
|
|
1800
|
-
previousValue,
|
|
1801
|
-
};
|
|
1802
|
-
return localMetadata;
|
|
1803
|
-
}
|
|
1804
|
-
|
|
1805
1770
|
/**
|
|
1806
1771
|
* Process a set operation.
|
|
1807
1772
|
* @param msg - The message from the server to apply.
|
|
@@ -1809,7 +1774,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1809
1774
|
* @param local - Whether the message originated from the local client
|
|
1810
1775
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1811
1776
|
* For messages from a remote client, this will be undefined.
|
|
1812
|
-
* @internal
|
|
1813
1777
|
*/
|
|
1814
1778
|
public processSetMessage(
|
|
1815
1779
|
msg: ISequencedDocumentMessage,
|
|
@@ -1834,28 +1798,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1834
1798
|
this.setCore(op.key, context!, local);
|
|
1835
1799
|
}
|
|
1836
1800
|
|
|
1837
|
-
/**
|
|
1838
|
-
* Apply set operation locally and generate metadata
|
|
1839
|
-
* @param op - Op to apply
|
|
1840
|
-
* @returns metadata generated for stahed op
|
|
1841
|
-
*/
|
|
1842
|
-
public applyStashedSetMessage(
|
|
1843
|
-
op: IDirectorySetOperation,
|
|
1844
|
-
context: ILocalValue,
|
|
1845
|
-
): IKeyEditLocalOpMetadata {
|
|
1846
|
-
this.throwIfDisposed();
|
|
1847
|
-
// Set the value locally.
|
|
1848
|
-
const previousValue = this.setCore(op.key, context, true);
|
|
1849
|
-
|
|
1850
|
-
// Create metadata
|
|
1851
|
-
const pendingMessageId = this.getKeyMessageId(op);
|
|
1852
|
-
const localMetadata: IKeyEditLocalOpMetadata = {
|
|
1853
|
-
type: "edit",
|
|
1854
|
-
pendingMessageId,
|
|
1855
|
-
previousValue,
|
|
1856
|
-
};
|
|
1857
|
-
return localMetadata;
|
|
1858
|
-
}
|
|
1859
1801
|
/**
|
|
1860
1802
|
* Process a create subdirectory operation.
|
|
1861
1803
|
* @param msg - The message from the server to apply.
|
|
@@ -1863,7 +1805,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1863
1805
|
* @param local - Whether the message originated from the local client
|
|
1864
1806
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1865
1807
|
* For messages from a remote client, this will be undefined.
|
|
1866
|
-
* @internal
|
|
1867
1808
|
*/
|
|
1868
1809
|
public processCreateSubDirectoryMessage(
|
|
1869
1810
|
msg: ISequencedDocumentMessage,
|
|
@@ -1889,30 +1830,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1889
1830
|
);
|
|
1890
1831
|
}
|
|
1891
1832
|
|
|
1892
|
-
/**
|
|
1893
|
-
* Apply createSubDirectory operation locally and generate metadata
|
|
1894
|
-
* @param op - Op to apply
|
|
1895
|
-
* @returns metadata generated for stahed op
|
|
1896
|
-
*/
|
|
1897
|
-
public applyStashedCreateSubDirMessage(
|
|
1898
|
-
op: IDirectoryCreateSubDirectoryOperation,
|
|
1899
|
-
): ICreateSubDirLocalOpMetadata {
|
|
1900
|
-
this.throwIfDisposed();
|
|
1901
|
-
// Create the sub directory locally first.
|
|
1902
|
-
this.createSubDirectoryCore(
|
|
1903
|
-
op.subdirName,
|
|
1904
|
-
true,
|
|
1905
|
-
this.getLocalSeq(),
|
|
1906
|
-
this.runtime.clientId ?? "detached",
|
|
1907
|
-
);
|
|
1908
|
-
this.updatePendingSubDirMessageCount(op);
|
|
1909
|
-
|
|
1910
|
-
const localOpMetadata: ICreateSubDirLocalOpMetadata = {
|
|
1911
|
-
type: "createSubDir",
|
|
1912
|
-
};
|
|
1913
|
-
return localOpMetadata;
|
|
1914
|
-
}
|
|
1915
|
-
|
|
1916
1833
|
/**
|
|
1917
1834
|
* Process a delete subdirectory operation.
|
|
1918
1835
|
* @param msg - The message from the server to apply.
|
|
@@ -1920,7 +1837,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1920
1837
|
* @param local - Whether the message originated from the local client
|
|
1921
1838
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1922
1839
|
* For messages from a remote client, this will be undefined.
|
|
1923
|
-
* @internal
|
|
1924
1840
|
*/
|
|
1925
1841
|
public processDeleteSubDirectoryMessage(
|
|
1926
1842
|
msg: ISequencedDocumentMessage,
|
|
@@ -1940,24 +1856,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1940
1856
|
this.deleteSubDirectoryCore(op.subdirName, local);
|
|
1941
1857
|
}
|
|
1942
1858
|
|
|
1943
|
-
/**
|
|
1944
|
-
* Apply deleteSubDirectory operation locally and generate metadata
|
|
1945
|
-
* @param op - Op to apply
|
|
1946
|
-
* @returns metadata generated for stahed op
|
|
1947
|
-
*/
|
|
1948
|
-
public applyStashedDeleteSubDirMessage(
|
|
1949
|
-
op: IDirectoryDeleteSubDirectoryOperation,
|
|
1950
|
-
): IDeleteSubDirLocalOpMetadata {
|
|
1951
|
-
this.throwIfDisposed();
|
|
1952
|
-
const subDir = this.deleteSubDirectoryCore(op.subdirName, true);
|
|
1953
|
-
this.updatePendingSubDirMessageCount(op);
|
|
1954
|
-
const metadata: IDeleteSubDirLocalOpMetadata = {
|
|
1955
|
-
type: "deleteSubDir",
|
|
1956
|
-
subDirectory: subDir,
|
|
1957
|
-
};
|
|
1958
|
-
return metadata;
|
|
1959
|
-
}
|
|
1960
|
-
|
|
1961
1859
|
/**
|
|
1962
1860
|
* Submit a clear operation.
|
|
1963
1861
|
* @param op - The operation
|
|
@@ -1980,7 +1878,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1980
1878
|
/**
|
|
1981
1879
|
* Resubmit a clear operation.
|
|
1982
1880
|
* @param op - The operation
|
|
1983
|
-
* @internal
|
|
1984
1881
|
*/
|
|
1985
1882
|
public resubmitClearMessage(op: IDirectoryClearOperation, localOpMetadata: unknown): void {
|
|
1986
1883
|
assert(
|
|
@@ -2003,10 +1900,10 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2003
1900
|
// We don't reuse the metadata pendingMessageId but send a new one on each submit.
|
|
2004
1901
|
const pendingMessageId = ++this.pendingMessageId;
|
|
2005
1902
|
const pendingMessageIds = this.pendingKeys.get(op.key);
|
|
2006
|
-
if (pendingMessageIds
|
|
2007
|
-
pendingMessageIds.push(pendingMessageId);
|
|
2008
|
-
} else {
|
|
1903
|
+
if (pendingMessageIds === undefined) {
|
|
2009
1904
|
this.pendingKeys.set(op.key, [pendingMessageId]);
|
|
1905
|
+
} else {
|
|
1906
|
+
pendingMessageIds.push(pendingMessageId);
|
|
2010
1907
|
}
|
|
2011
1908
|
return pendingMessageId;
|
|
2012
1909
|
}
|
|
@@ -2027,7 +1924,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2027
1924
|
* Submit a key message to remote clients based on a previous submit.
|
|
2028
1925
|
* @param op - The map key message
|
|
2029
1926
|
* @param localOpMetadata - Metadata from the previous submit
|
|
2030
|
-
* @internal
|
|
2031
1927
|
*/
|
|
2032
1928
|
public resubmitKeyMessage(op: IDirectoryKeyOperation, localOpMetadata: unknown): void {
|
|
2033
1929
|
assert(
|
|
@@ -2040,9 +1936,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2040
1936
|
// Only submit the op, if we have record for it, otherwise it is possible that the older instance
|
|
2041
1937
|
// is already deleted, in which case we don't need to submit the op.
|
|
2042
1938
|
if (pendingMessageIds !== undefined) {
|
|
2043
|
-
const index = pendingMessageIds.
|
|
2044
|
-
(id) => id === localOpMetadata.pendingMessageId,
|
|
2045
|
-
);
|
|
1939
|
+
const index = pendingMessageIds.indexOf(localOpMetadata.pendingMessageId);
|
|
2046
1940
|
if (index === -1) {
|
|
2047
1941
|
return;
|
|
2048
1942
|
}
|
|
@@ -2054,12 +1948,12 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2054
1948
|
}
|
|
2055
1949
|
}
|
|
2056
1950
|
|
|
2057
|
-
private incrementPendingSubDirCount(map: Map<string, number>, subDirName: string) {
|
|
1951
|
+
private incrementPendingSubDirCount(map: Map<string, number>, subDirName: string): void {
|
|
2058
1952
|
const count = map.get(subDirName) ?? 0;
|
|
2059
1953
|
map.set(subDirName, count + 1);
|
|
2060
1954
|
}
|
|
2061
1955
|
|
|
2062
|
-
private decrementPendingSubDirCount(map: Map<string, number>, subDirName: string) {
|
|
1956
|
+
private decrementPendingSubDirCount(map: Map<string, number>, subDirName: string): void {
|
|
2063
1957
|
const count = map.get(subDirName) ?? 0;
|
|
2064
1958
|
map.set(subDirName, count - 1);
|
|
2065
1959
|
if (count <= 1) {
|
|
@@ -2071,7 +1965,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2071
1965
|
* Update the count for pending create/delete of the sub directory so that it can be validated on receiving op
|
|
2072
1966
|
* or while resubmitting the op.
|
|
2073
1967
|
*/
|
|
2074
|
-
private updatePendingSubDirMessageCount(op: IDirectorySubDirectoryOperation) {
|
|
1968
|
+
private updatePendingSubDirMessageCount(op: IDirectorySubDirectoryOperation): void {
|
|
2075
1969
|
if (op.type === "deleteSubDirectory") {
|
|
2076
1970
|
this.incrementPendingSubDirCount(
|
|
2077
1971
|
this.pendingDeleteSubDirectoriesTracker,
|
|
@@ -2122,7 +2016,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2122
2016
|
* Submit a subdirectory operation again
|
|
2123
2017
|
* @param op - The operation
|
|
2124
2018
|
* @param localOpMetadata - metadata submitted with the op originally
|
|
2125
|
-
* @internal
|
|
2126
2019
|
*/
|
|
2127
2020
|
public resubmitSubDirectoryMessage(
|
|
2128
2021
|
op: IDirectorySubDirectoryOperation,
|
|
@@ -2166,7 +2059,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2166
2059
|
* Get the storage of this subdirectory in a serializable format, to be used in snapshotting.
|
|
2167
2060
|
* @param serializer - The serializer to use to serialize handles in its values.
|
|
2168
2061
|
* @returns The JSONable string representing the storage of this subdirectory
|
|
2169
|
-
* @internal
|
|
2170
2062
|
*/
|
|
2171
2063
|
public *getSerializedStorage(
|
|
2172
2064
|
serializer: IFluidSerializer,
|
|
@@ -2179,11 +2071,11 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2179
2071
|
}
|
|
2180
2072
|
}
|
|
2181
2073
|
|
|
2182
|
-
public getSerializableCreateInfo() {
|
|
2074
|
+
public getSerializableCreateInfo(): ICreateInfo {
|
|
2183
2075
|
this.throwIfDisposed();
|
|
2184
2076
|
const createInfo: ICreateInfo = {
|
|
2185
2077
|
csn: this.seqData.seq,
|
|
2186
|
-
ccIds:
|
|
2078
|
+
ccIds: [...this.clientIds],
|
|
2187
2079
|
};
|
|
2188
2080
|
return createInfo;
|
|
2189
2081
|
}
|
|
@@ -2192,7 +2084,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2192
2084
|
* Populate a key value in this subdirectory's storage, to be used when loading from snapshot.
|
|
2193
2085
|
* @param key - The key to populate
|
|
2194
2086
|
* @param localValue - The local value to populate into it
|
|
2195
|
-
* @internal
|
|
2196
2087
|
*/
|
|
2197
2088
|
public populateStorage(key: string, localValue: ILocalValue): void {
|
|
2198
2089
|
this.throwIfDisposed();
|
|
@@ -2203,7 +2094,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2203
2094
|
* Populate a subdirectory into this subdirectory, to be used when loading from snapshot.
|
|
2204
2095
|
* @param subdirName - The name of the subdirectory to add
|
|
2205
2096
|
* @param newSubDir - The new subdirectory to add
|
|
2206
|
-
* @internal
|
|
2207
2097
|
*/
|
|
2208
2098
|
public populateSubDirectory(subdirName: string, newSubDir: SubDirectory): void {
|
|
2209
2099
|
this.throwIfDisposed();
|
|
@@ -2215,7 +2105,6 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2215
2105
|
* value so op handlers can be retrieved
|
|
2216
2106
|
* @param key - The key to retrieve from
|
|
2217
2107
|
* @returns The local value
|
|
2218
|
-
* @internal
|
|
2219
2108
|
*/
|
|
2220
2109
|
public getLocalValue<T extends ILocalValue = ILocalValue>(key: string): T {
|
|
2221
2110
|
this.throwIfDisposed();
|
|
@@ -2268,46 +2157,62 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2268
2157
|
throw new Error("Rollback op does match last clear");
|
|
2269
2158
|
}
|
|
2270
2159
|
} else if ((op.type === "delete" || op.type === "set") && localOpMetadata.type === "edit") {
|
|
2160
|
+
const key: unknown = op.key;
|
|
2161
|
+
assert(key !== undefined, 0x8ad /* "key" property is missing from edit operation. */);
|
|
2162
|
+
assert(
|
|
2163
|
+
typeof key === "string",
|
|
2164
|
+
0x8ae /* "key" property in edit operation is misconfigured. Expected a string. */,
|
|
2165
|
+
);
|
|
2166
|
+
|
|
2271
2167
|
if (localOpMetadata.previousValue === undefined) {
|
|
2272
|
-
this.deleteCore(
|
|
2168
|
+
this.deleteCore(key, true);
|
|
2273
2169
|
} else {
|
|
2274
|
-
this.setCore(
|
|
2170
|
+
this.setCore(key, localOpMetadata.previousValue, true);
|
|
2275
2171
|
}
|
|
2276
2172
|
|
|
2277
|
-
this.rollbackPendingMessageId(
|
|
2278
|
-
this.pendingKeys,
|
|
2279
|
-
op.key as string,
|
|
2280
|
-
localOpMetadata.pendingMessageId,
|
|
2281
|
-
);
|
|
2173
|
+
this.rollbackPendingMessageId(this.pendingKeys, key, localOpMetadata.pendingMessageId);
|
|
2282
2174
|
} else if (op.type === "createSubDirectory" && localOpMetadata.type === "createSubDir") {
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
op.subdirName as string,
|
|
2175
|
+
const subdirName: unknown = op.subdirName;
|
|
2176
|
+
assert(
|
|
2177
|
+
subdirName !== undefined,
|
|
2178
|
+
0x8af /* "subdirName" property is missing from "createSubDirectory" operation. */,
|
|
2288
2179
|
);
|
|
2180
|
+
assert(
|
|
2181
|
+
typeof subdirName === "string",
|
|
2182
|
+
0x8b0 /* "subdirName" property in "createSubDirectory" operation is misconfigured. Expected a string. */,
|
|
2183
|
+
);
|
|
2184
|
+
|
|
2185
|
+
this.deleteSubDirectoryCore(subdirName, true);
|
|
2186
|
+
this.decrementPendingSubDirCount(this.pendingCreateSubDirectoriesTracker, subdirName);
|
|
2289
2187
|
} else if (op.type === "deleteSubDirectory" && localOpMetadata.type === "deleteSubDir") {
|
|
2188
|
+
const subdirName: unknown = op.subdirName;
|
|
2189
|
+
assert(
|
|
2190
|
+
subdirName !== undefined,
|
|
2191
|
+
0x8b1 /* "subdirName" property is missing from "deleteSubDirectory" operation. */,
|
|
2192
|
+
);
|
|
2193
|
+
assert(
|
|
2194
|
+
typeof subdirName === "string",
|
|
2195
|
+
0x8b2 /* "subdirName" property in "deleteSubDirectory" operation is misconfigured. Expected a string. */,
|
|
2196
|
+
);
|
|
2197
|
+
|
|
2290
2198
|
if (localOpMetadata.subDirectory !== undefined) {
|
|
2291
2199
|
this.undeleteSubDirectoryTree(localOpMetadata.subDirectory);
|
|
2292
2200
|
// don't need to register events because deleting never unregistered
|
|
2293
|
-
this._subdirectories.set(
|
|
2201
|
+
this._subdirectories.set(subdirName, localOpMetadata.subDirectory);
|
|
2294
2202
|
// Restore the record in creation tracker
|
|
2295
2203
|
if (isAcknowledgedOrDetached(localOpMetadata.subDirectory.seqData)) {
|
|
2296
|
-
this.ackedCreationSeqTracker.set(
|
|
2204
|
+
this.ackedCreationSeqTracker.set(subdirName, {
|
|
2297
2205
|
...localOpMetadata.subDirectory.seqData,
|
|
2298
2206
|
});
|
|
2299
2207
|
} else {
|
|
2300
|
-
this.localCreationSeqTracker.set(
|
|
2208
|
+
this.localCreationSeqTracker.set(subdirName, {
|
|
2301
2209
|
...localOpMetadata.subDirectory.seqData,
|
|
2302
2210
|
});
|
|
2303
2211
|
}
|
|
2304
|
-
this.emit("subDirectoryCreated",
|
|
2212
|
+
this.emit("subDirectoryCreated", subdirName, true, this);
|
|
2305
2213
|
}
|
|
2306
2214
|
|
|
2307
|
-
this.decrementPendingSubDirCount(
|
|
2308
|
-
this.pendingDeleteSubDirectoriesTracker,
|
|
2309
|
-
op.subDirName as string,
|
|
2310
|
-
);
|
|
2215
|
+
this.decrementPendingSubDirCount(this.pendingDeleteSubDirectoriesTracker, subdirName);
|
|
2311
2216
|
} else {
|
|
2312
2217
|
throw new Error("Unsupported op for rollback");
|
|
2313
2218
|
}
|
|
@@ -2397,7 +2302,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2397
2302
|
* can be deleted and created again, then this finds if the message is for current instance of directory or not.
|
|
2398
2303
|
* @param msg - message for the directory
|
|
2399
2304
|
*/
|
|
2400
|
-
private isMessageForCurrentInstanceOfSubDirectory(msg: ISequencedDocumentMessage) {
|
|
2305
|
+
private isMessageForCurrentInstanceOfSubDirectory(msg: ISequencedDocumentMessage): boolean {
|
|
2401
2306
|
// If the message is either from the creator of directory or this directory was created when
|
|
2402
2307
|
// container was detached or in case this directory is already live(known to other clients)
|
|
2403
2308
|
// and the op was created after the directory was created then apply this op.
|
|
@@ -2625,10 +2530,10 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2625
2530
|
* Store the sequnce numbers of newly created subdirectory to the proper creation tracker, based
|
|
2626
2531
|
* on whether the creation behavior has been ack'd or not
|
|
2627
2532
|
*/
|
|
2628
|
-
if (
|
|
2629
|
-
this.localCreationSeqTracker.set(subdirName, { ...seqData });
|
|
2630
|
-
} else {
|
|
2533
|
+
if (isAcknowledgedOrDetached(seqData)) {
|
|
2631
2534
|
this.ackedCreationSeqTracker.set(subdirName, { ...seqData });
|
|
2535
|
+
} else {
|
|
2536
|
+
this.localCreationSeqTracker.set(subdirName, { ...seqData });
|
|
2632
2537
|
}
|
|
2633
2538
|
|
|
2634
2539
|
this.registerEventsOnSubDirectory(subDir, subdirName);
|