@fluidframework/matrix 2.41.0-338186 → 2.41.0

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.
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/matrix";
8
- export const pkgVersion = "2.41.0-338186";
8
+ export const pkgVersion = "2.41.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,wBAAwB,CAAC;AAChD,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/matrix\";\nexport const pkgVersion = \"2.41.0-338186\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,wBAAwB,CAAC;AAChD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/matrix\";\nexport const pkgVersion = \"2.41.0\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/matrix",
3
- "version": "2.41.0-338186",
3
+ "version": "2.41.0",
4
4
  "description": "Distributed matrix",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -81,17 +81,17 @@
81
81
  "temp-directory": "nyc/.nyc_output"
82
82
  },
83
83
  "dependencies": {
84
- "@fluid-internal/client-utils": "2.41.0-338186",
85
- "@fluidframework/core-interfaces": "2.41.0-338186",
86
- "@fluidframework/core-utils": "2.41.0-338186",
87
- "@fluidframework/datastore-definitions": "2.41.0-338186",
88
- "@fluidframework/driver-definitions": "2.41.0-338186",
89
- "@fluidframework/driver-utils": "2.41.0-338186",
90
- "@fluidframework/merge-tree": "2.41.0-338186",
91
- "@fluidframework/runtime-definitions": "2.41.0-338186",
92
- "@fluidframework/runtime-utils": "2.41.0-338186",
93
- "@fluidframework/shared-object-base": "2.41.0-338186",
94
- "@fluidframework/telemetry-utils": "2.41.0-338186",
84
+ "@fluid-internal/client-utils": "~2.41.0",
85
+ "@fluidframework/core-interfaces": "~2.41.0",
86
+ "@fluidframework/core-utils": "~2.41.0",
87
+ "@fluidframework/datastore-definitions": "~2.41.0",
88
+ "@fluidframework/driver-definitions": "~2.41.0",
89
+ "@fluidframework/driver-utils": "~2.41.0",
90
+ "@fluidframework/merge-tree": "~2.41.0",
91
+ "@fluidframework/runtime-definitions": "~2.41.0",
92
+ "@fluidframework/runtime-utils": "~2.41.0",
93
+ "@fluidframework/shared-object-base": "~2.41.0",
94
+ "@fluidframework/telemetry-utils": "~2.41.0",
95
95
  "@tiny-calc/nano": "0.0.0-alpha.5",
96
96
  "double-ended-queue": "^2.1.0-0",
97
97
  "tslib": "^1.10.0"
@@ -99,17 +99,17 @@
99
99
  "devDependencies": {
100
100
  "@arethetypeswrong/cli": "^0.17.1",
101
101
  "@biomejs/biome": "~1.9.3",
102
- "@fluid-internal/mocha-test-setup": "2.41.0-338186",
103
- "@fluid-private/stochastic-test-utils": "2.41.0-338186",
104
- "@fluid-private/test-dds-utils": "2.41.0-338186",
102
+ "@fluid-internal/mocha-test-setup": "~2.41.0",
103
+ "@fluid-private/stochastic-test-utils": "~2.41.0",
104
+ "@fluid-private/test-dds-utils": "~2.41.0",
105
105
  "@fluid-tools/benchmark": "^0.51.0",
106
106
  "@fluid-tools/build-cli": "^0.55.0",
107
107
  "@fluidframework/build-common": "^2.0.3",
108
108
  "@fluidframework/build-tools": "^0.55.0",
109
- "@fluidframework/container-definitions": "2.41.0-338186",
110
- "@fluidframework/eslint-config-fluid": "^5.7.3",
109
+ "@fluidframework/container-definitions": "~2.41.0",
110
+ "@fluidframework/eslint-config-fluid": "^5.7.4",
111
111
  "@fluidframework/matrix-previous": "npm:@fluidframework/matrix@2.40.0",
112
- "@fluidframework/test-runtime-utils": "2.41.0-338186",
112
+ "@fluidframework/test-runtime-utils": "~2.41.0",
113
113
  "@microsoft/api-extractor": "7.52.8",
114
114
  "@tiny-calc/micro": "0.0.0-alpha.5",
115
115
  "@types/double-ended-queue": "^2.1.0",
package/src/matrix.ts CHANGED
@@ -204,6 +204,15 @@ export interface ISharedMatrix<T = any>
204
204
  switchSetCellPolicy(): void;
205
205
  }
206
206
 
207
+ type FirstWriterWinsPolicy =
208
+ | { state: "off" }
209
+ | { state: "local" }
210
+ | {
211
+ state: "on";
212
+ switchOpSeqNumber: number;
213
+ cellLastWriteTracker: SparseArray2D<CellLastWriteTrackerItem>;
214
+ };
215
+
207
216
  /**
208
217
  * A SharedMatrix holds a rectangular 2D array of values. Supported operations
209
218
  * include setting values and inserting/removing rows and columns.
@@ -244,10 +253,10 @@ export class SharedMatrix<T = any>
244
253
 
245
254
  private cells = new SparseArray2D<MatrixItem<T>>(); // Stores cell values.
246
255
  private readonly pending = new SparseArray2D<number>(); // Tracks pending writes.
247
- private cellLastWriteTracker = new SparseArray2D<CellLastWriteTrackerItem>(); // Tracks last writes sequence number and clientId in a cell.
248
- // Tracks the seq number of Op at which policy switch happens from Last Write Win to First Write Win.
249
- private setCellLwwToFwwPolicySwitchOpSeqNumber: number;
250
- private userSwitchedSetCellPolicy = false; // Set to true when the user calls switchPolicy.
256
+
257
+ private fwwPolicy: FirstWriterWinsPolicy = {
258
+ state: "off",
259
+ };
251
260
 
252
261
  // Used to track if there is any reentrancy in setCell code.
253
262
  private reentrantCount: number = 0;
@@ -267,7 +276,6 @@ export class SharedMatrix<T = any>
267
276
  ) {
268
277
  super(id, runtime, attributes, "fluid_matrix_");
269
278
 
270
- this.setCellLwwToFwwPolicySwitchOpSeqNumber = -1;
271
279
  this.rows = new PermutationVector(
272
280
  SnapshotPath.rows,
273
281
  this.logger,
@@ -333,7 +341,7 @@ export class SharedMatrix<T = any>
333
341
  }
334
342
 
335
343
  public isSetCellConflictResolutionPolicyFWW(): boolean {
336
- return this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1 || this.userSwitchedSetCellPolicy;
344
+ return this.fwwPolicy.state !== "off";
337
345
  }
338
346
 
339
347
  public getCell(row: number, col: number): MatrixItem<T> {
@@ -470,8 +478,7 @@ export class SharedMatrix<T = any>
470
478
  row,
471
479
  col,
472
480
  value,
473
- fwwMode:
474
- this.userSwitchedSetCellPolicy || this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1,
481
+ fwwMode: this.fwwPolicy.state !== "off",
475
482
  };
476
483
 
477
484
  const rowsRef = this.createOpMetadataLocalRef(this.rows, row, localSeq);
@@ -668,15 +675,29 @@ export class SharedMatrix<T = any>
668
675
  SnapshotPath.cols,
669
676
  this.cols.summarize(this.runtime, this.handle, serializer),
670
677
  );
671
- const artifactsToSummarize = [
672
- this.cells.snapshot(),
673
- this.pending.snapshot(),
674
- this.setCellLwwToFwwPolicySwitchOpSeqNumber,
675
- ];
678
+ const artifactsToSummarize: (
679
+ | undefined
680
+ | number
681
+ | ReturnType<SparseArray2D<MatrixItem<T> | number>["snapshot"]>
682
+ )[] = [this.cells.snapshot(), this.pending.snapshot()];
676
683
 
677
684
  // Only need to store it in the snapshot if we have switched the policy already.
678
- if (this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1) {
679
- artifactsToSummarize.push(this.cellLastWriteTracker.snapshot());
685
+ if (this.fwwPolicy.state === "on") {
686
+ artifactsToSummarize.push(
687
+ this.fwwPolicy.switchOpSeqNumber,
688
+ this.fwwPolicy.cellLastWriteTracker.snapshot(),
689
+ );
690
+ } else {
691
+ // back-compat: used -1 for disabled
692
+ artifactsToSummarize.push(
693
+ -1,
694
+ /*
695
+ * we should set undefined in place of cellLastWriteTracker to ensure the number of array entries is consistent.
696
+ * Doing that currently breaks snapshot tests. Its is probably fine, but if new elements are ever added, we need
697
+ * ensure undefined is also set.
698
+ */
699
+ // undefined
700
+ );
680
701
  }
681
702
  builder.addBlob(
682
703
  SnapshotPath.cells,
@@ -786,19 +807,15 @@ export class SharedMatrix<T = any>
786
807
  this.rows.removeLocalReferencePosition(rowsRef);
787
808
  this.cols.removeLocalReferencePosition(colsRef);
788
809
  if (row !== undefined && col !== undefined && row >= 0 && col >= 0) {
789
- const lastCellModificationDetails = this.cellLastWriteTracker.getCell(
790
- rowHandle,
791
- colHandle,
792
- );
793
810
  // If the mode is LWW, then send the op.
794
811
  // Otherwise if the current mode is FWW and if we generated this op, after seeing the
795
812
  // last set op, or it is the first set op for the cell, then regenerate the op,
796
813
  // otherwise raise conflict. We want to check the current mode here and not that
797
814
  // whether op was made in FWW or not.
798
815
  if (
799
- this.setCellLwwToFwwPolicySwitchOpSeqNumber === -1 ||
800
- lastCellModificationDetails === undefined ||
801
- referenceSeqNumber >= lastCellModificationDetails.seqNum
816
+ this.fwwPolicy.state !== "on" ||
817
+ referenceSeqNumber >=
818
+ (this.fwwPolicy.cellLastWriteTracker.getCell(rowHandle, colHandle)?.seqNum ?? 0)
802
819
  ) {
803
820
  this.sendSetCellOp(row, col, setOp.value, rowHandle, colHandle, localSeq);
804
821
  } else if (this.pending.getCell(rowHandle, colHandle) !== undefined) {
@@ -854,11 +871,21 @@ export class SharedMatrix<T = any>
854
871
  ];
855
872
 
856
873
  this.cells = SparseArray2D.load(cellData);
857
- this.setCellLwwToFwwPolicySwitchOpSeqNumber =
858
- setCellLwwToFwwPolicySwitchOpSeqNumber ?? -1;
859
- if (cellLastWriteTracker !== undefined) {
860
- this.cellLastWriteTracker = SparseArray2D.load(cellLastWriteTracker);
861
- }
874
+ // back-compat: used -1 for disabled, also may not exist
875
+ const switchOpSeqNumber =
876
+ setCellLwwToFwwPolicySwitchOpSeqNumber === -1
877
+ ? undefined
878
+ : (setCellLwwToFwwPolicySwitchOpSeqNumber ?? undefined);
879
+ this.fwwPolicy =
880
+ switchOpSeqNumber === undefined
881
+ ? {
882
+ state: "off",
883
+ }
884
+ : {
885
+ state: "on",
886
+ switchOpSeqNumber,
887
+ cellLastWriteTracker: SparseArray2D.load(cellLastWriteTracker),
888
+ };
862
889
  } catch (error) {
863
890
  this.logger.sendErrorEvent({ eventName: "MatrixLoadFailed" }, error);
864
891
  }
@@ -874,11 +901,11 @@ export class SharedMatrix<T = any>
874
901
  message: ISequencedDocumentMessage,
875
902
  ): boolean {
876
903
  assert(
877
- this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1,
904
+ this.fwwPolicy.state === "on",
878
905
  0x85f /* should be in Fww mode when calling this method */,
879
906
  );
880
907
  assert(message.clientId !== null, 0x860 /* clientId should not be null */);
881
- const lastCellModificationDetails = this.cellLastWriteTracker.getCell(
908
+ const lastCellModificationDetails = this.fwwPolicy.cellLastWriteTracker.getCell(
882
909
  rowHandle,
883
910
  colHandle,
884
911
  );
@@ -927,11 +954,13 @@ export class SharedMatrix<T = any>
927
954
  );
928
955
 
929
956
  const { row, col, value, fwwMode } = contents;
930
- const isPreviousSetCellPolicyModeFWW =
931
- this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1;
932
957
  // If this is the first op notifying us of the policy change, then set the policy change seq number.
933
- if (this.setCellLwwToFwwPolicySwitchOpSeqNumber === -1 && fwwMode === true) {
934
- this.setCellLwwToFwwPolicySwitchOpSeqNumber = msg.sequenceNumber;
958
+ if (fwwMode === true && this.fwwPolicy.state !== "on") {
959
+ this.fwwPolicy = {
960
+ state: "on",
961
+ switchOpSeqNumber: msg.sequenceNumber,
962
+ cellLastWriteTracker: new SparseArray2D(),
963
+ };
935
964
  }
936
965
 
937
966
  assert(msg.clientId !== null, 0x861 /* clientId should not be null!! */);
@@ -945,11 +974,10 @@ export class SharedMatrix<T = any>
945
974
  // If policy is switched and cell should be modified too based on policy, then update the tracker.
946
975
  // If policy is not switched, then also update the tracker in case it is the latest.
947
976
  if (
948
- (this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1 &&
949
- this.shouldSetCellBasedOnFWW(rowHandle, colHandle, msg)) ||
950
- (this.setCellLwwToFwwPolicySwitchOpSeqNumber === -1 && isLatestPendingOp)
977
+ this.fwwPolicy.state === "on" &&
978
+ this.shouldSetCellBasedOnFWW(rowHandle, colHandle, msg)
951
979
  ) {
952
- this.cellLastWriteTracker.setCell(rowHandle, colHandle, {
980
+ this.fwwPolicy.cellLastWriteTracker.setCell(rowHandle, colHandle, {
953
981
  seqNum: msg.sequenceNumber,
954
982
  clientId: msg.clientId,
955
983
  });
@@ -971,17 +999,14 @@ export class SharedMatrix<T = any>
971
999
  isHandleValid(rowHandle) && isHandleValid(colHandle),
972
1000
  0x022 /* "SharedMatrix row and/or col handles are invalid!" */,
973
1001
  );
974
- if (this.setCellLwwToFwwPolicySwitchOpSeqNumber > -1) {
1002
+ if (this.fwwPolicy.state === "on") {
975
1003
  // If someone tried to Overwrite the cell value or first write on this cell or
976
1004
  // same client tried to modify the cell or if the previous mode was LWW, then we need to still
977
1005
  // overwrite the cell and raise conflict if we have pending changes as our change is going to be lost.
978
- if (
979
- !isPreviousSetCellPolicyModeFWW ||
980
- this.shouldSetCellBasedOnFWW(rowHandle, colHandle, msg)
981
- ) {
1006
+ if (this.shouldSetCellBasedOnFWW(rowHandle, colHandle, msg)) {
982
1007
  const previousValue = this.cells.getCell(rowHandle, colHandle);
983
1008
  this.cells.setCell(rowHandle, colHandle, value);
984
- this.cellLastWriteTracker.setCell(rowHandle, colHandle, {
1009
+ this.fwwPolicy.cellLastWriteTracker.setCell(rowHandle, colHandle, {
985
1010
  seqNum: msg.sequenceNumber,
986
1011
  clientId: msg.clientId,
987
1012
  });
@@ -1006,10 +1031,6 @@ export class SharedMatrix<T = any>
1006
1031
  // If there is a pending (unACKed) local write to the same cell, skip the current op
1007
1032
  // since it "happened before" the pending write.
1008
1033
  this.cells.setCell(rowHandle, colHandle, value);
1009
- this.cellLastWriteTracker.setCell(rowHandle, colHandle, {
1010
- seqNum: msg.sequenceNumber,
1011
- clientId: msg.clientId,
1012
- });
1013
1034
  for (const consumer of this.consumers.values()) {
1014
1035
  consumer.cellsChanged(adjustedRow, adjustedCol, 1, 1, this);
1015
1036
  }
@@ -1051,7 +1072,12 @@ export class SharedMatrix<T = any>
1051
1072
  for (const rowHandle of rowHandles) {
1052
1073
  this.cells.clearRows(/* rowStart: */ rowHandle, /* rowCount: */ 1);
1053
1074
  this.pending.clearRows(/* rowStart: */ rowHandle, /* rowCount: */ 1);
1054
- this.cellLastWriteTracker.clearRows(/* rowStart: */ rowHandle, /* rowCount: */ 1);
1075
+ if (this.fwwPolicy.state === "on") {
1076
+ this.fwwPolicy.cellLastWriteTracker?.clearRows(
1077
+ /* rowStart: */ rowHandle,
1078
+ /* rowCount: */ 1,
1079
+ );
1080
+ }
1055
1081
  }
1056
1082
  };
1057
1083
 
@@ -1059,17 +1085,24 @@ export class SharedMatrix<T = any>
1059
1085
  for (const colHandle of colHandles) {
1060
1086
  this.cells.clearCols(/* colStart: */ colHandle, /* colCount: */ 1);
1061
1087
  this.pending.clearCols(/* colStart: */ colHandle, /* colCount: */ 1);
1062
- this.cellLastWriteTracker.clearCols(/* colStart: */ colHandle, /* colCount: */ 1);
1088
+ if (this.fwwPolicy.state === "on") {
1089
+ this.fwwPolicy.cellLastWriteTracker?.clearCols(
1090
+ /* colStart: */ colHandle,
1091
+ /* colCount: */ 1,
1092
+ );
1093
+ }
1063
1094
  }
1064
1095
  };
1065
1096
 
1066
1097
  public switchSetCellPolicy(): void {
1067
- if (this.setCellLwwToFwwPolicySwitchOpSeqNumber === -1) {
1068
- if (this.isAttached()) {
1069
- this.userSwitchedSetCellPolicy = true;
1070
- } else {
1071
- this.setCellLwwToFwwPolicySwitchOpSeqNumber = 0;
1072
- }
1098
+ if (this.fwwPolicy.state === "off") {
1099
+ this.fwwPolicy = this.isAttached()
1100
+ ? { state: "local" }
1101
+ : {
1102
+ state: "on",
1103
+ switchOpSeqNumber: 0,
1104
+ cellLastWriteTracker: new SparseArray2D(),
1105
+ };
1073
1106
  }
1074
1107
  }
1075
1108
 
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/matrix";
9
- export const pkgVersion = "2.41.0-338186";
9
+ export const pkgVersion = "2.41.0";