@fluidframework/map 2.0.0-internal.8.0.3 → 2.0.0-internal.8.0.5

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.
@@ -186,6 +186,9 @@ class DirectoryCreationTracker {
186
186
  }, keys);
187
187
  return keys;
188
188
  }
189
+ get size() {
190
+ return this.keyToIndex.size;
191
+ }
189
192
  }
190
193
  /**
191
194
  * {@inheritDoc ISharedDirectory}
@@ -242,7 +245,7 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
242
245
  /**
243
246
  * Root of the SharedDirectory, most operations on the SharedDirectory itself act on the root.
244
247
  */
245
- this.root = new SubDirectory({ seq: 0, clientSeq: 0 }, new Set(), this, this.runtime, this.serializer, posix.sep);
248
+ this.root = new SubDirectory({ seq: 0, clientSeq: 0 }, new Set(), this, this.runtime, this.serializer, posix.sep, this.logger);
246
249
  /**
247
250
  * Mapping of op types to message handlers.
248
251
  */
@@ -476,10 +479,7 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
476
479
  // guaranteed during the serialization process. As a result, it is only essential to utilize the
477
480
  // "fake" client sequence number to signify the loading order, and there is no need to retain
478
481
  // the actual client sequence number at this point.
479
- if (createInfo !== undefined && createInfo.csn > -1) {
480
- // If csn is -1, then initialize it with 0, otherwise we will never process ops for this
481
- // sub directory. This could be done at serialization time too, but we need to maintain
482
- // back compat too and also we will actually know the state when it was serialized.
482
+ if (createInfo !== undefined && createInfo.csn > 0) {
483
483
  if (!tempSeqNums.has(createInfo.csn)) {
484
484
  tempSeqNums.set(createInfo.csn, 0);
485
485
  }
@@ -488,6 +488,13 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
488
488
  tempSeqNums.set(createInfo.csn, ++fakeClientSeq);
489
489
  }
490
490
  else {
491
+ /**
492
+ * 1. If csn is -1, then initialize it with 0, otherwise we will never process ops for this
493
+ * sub directory. This could be done at serialization time too, but we need to maintain
494
+ * back compat too and also we will actually know the state when it was serialized.
495
+ * 2. We need to make the csn = -1 and csn = 0 share the same counter, there are cases
496
+ * where both -1 and 0 coexist within a single document.
497
+ */
491
498
  seqData = {
492
499
  seq: 0,
493
500
  clientSeq: ++currentSubDir.localCreationSeq,
@@ -495,7 +502,7 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
495
502
  }
496
503
  newSubDir = new SubDirectory(seqData, createInfo !== undefined
497
504
  ? new Set(createInfo.ccIds)
498
- : new Set(), this, this.runtime, this.serializer, posix.join(currentSubDir.absolutePath, subdirName));
505
+ : new Set(), this, this.runtime, this.serializer, posix.join(currentSubDir.absolutePath, subdirName), this.logger);
499
506
  currentSubDir.populateSubDirectory(subdirName, newSubDir);
500
507
  // Record the newly inserted subdirectory to the creation tracker
501
508
  currentSubDir.ackedCreationSeqTracker.set(subdirName, {
@@ -797,6 +804,7 @@ function isDirectoryLocalOpMetadata(metadata) {
797
804
  function assertNonNullClientId(clientId) {
798
805
  (0, core_utils_1.assert)(clientId !== null, 0x6af /* client id should never be null */);
799
806
  }
807
+ let hasLoggedDirectoryInconsistency = false;
800
808
  /**
801
809
  * Node of the directory tree.
802
810
  * @sealed
@@ -811,7 +819,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
811
819
  * @param serializer - The serializer to serialize / parse handles
812
820
  * @param absolutePath - The absolute path of this IDirectory
813
821
  */
814
- constructor(seqData, clientIds, directory, runtime, serializer, absolutePath) {
822
+ constructor(seqData, clientIds, directory, runtime, serializer, absolutePath, logger) {
815
823
  super();
816
824
  this.seqData = seqData;
817
825
  this.clientIds = clientIds;
@@ -819,6 +827,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
819
827
  this.runtime = runtime;
820
828
  this.serializer = serializer;
821
829
  this.absolutePath = absolutePath;
830
+ this.logger = logger;
822
831
  /**
823
832
  * Tells if the sub directory is deleted or not.
824
833
  */
@@ -1027,7 +1036,23 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
1027
1036
  const ackedSubdirsInOrder = this.ackedCreationSeqTracker.keys();
1028
1037
  const localSubdirsInOrder = this.localCreationSeqTracker.keys((key) => !this.ackedCreationSeqTracker.has(key));
1029
1038
  const subdirNames = [...ackedSubdirsInOrder, ...localSubdirsInOrder];
1030
- (0, core_utils_1.assert)(subdirNames.length === this._subdirectories.size, 0x85c /* The count of keys for iteration should be consistent with the size of actual data */);
1039
+ if (subdirNames.length !== this._subdirectories.size) {
1040
+ // TODO: AB#7022: Hitting this block indicates that the eventual consistency scheme for ordering subdirectories
1041
+ // has failed. Fall back to previous directory behavior, which didn't guarantee ordering.
1042
+ // It's not currently clear how to reach this state, so log some diagnostics to help understand the issue.
1043
+ // This whole block should eventually be replaced by an assert that the two sizes align.
1044
+ if (!hasLoggedDirectoryInconsistency) {
1045
+ this.logger.sendTelemetryEvent({
1046
+ eventName: "inconsistentSubdirectoryOrdering",
1047
+ localKeyCount: this.localCreationSeqTracker.size,
1048
+ ackedKeyCount: this.ackedCreationSeqTracker.size,
1049
+ subdirNamesLength: subdirNames.length,
1050
+ subdirectoriesSize: this._subdirectories.size,
1051
+ });
1052
+ hasLoggedDirectoryInconsistency = true;
1053
+ }
1054
+ return this._subdirectories.entries();
1055
+ }
1031
1056
  const entriesIterator = {
1032
1057
  index: 0,
1033
1058
  dirs: this._subdirectories,
@@ -1872,7 +1897,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
1872
1897
  const subdir = this._subdirectories.get(subdirName);
1873
1898
  if (subdir === undefined) {
1874
1899
  const absolutePath = posix.join(this.absolutePath, subdirName);
1875
- const subDir = new SubDirectory({ ...seqData }, new Set([clientId]), this.directory, this.runtime, this.serializer, absolutePath);
1900
+ const subDir = new SubDirectory({ ...seqData }, new Set([clientId]), this.directory, this.runtime, this.serializer, absolutePath, this.logger);
1876
1901
  /**
1877
1902
  * Store the sequnce numbers of newly created subdirectory to the proper creation tracker, based
1878
1903
  * on whether the creation behavior has been ack'd or not