Skip to content

Commit 5632bb7

Browse files
authored
refactor(tree): Misc. cleanup in table schema APIs (#25333)
Removes a few private methods that really aren't needed, clears up some semantics regarding node id resolution, and removes nested transactions in column deletion.
1 parent 9b2b57c commit 5632bb7

File tree

1 file changed

+47
-126
lines changed

1 file changed

+47
-126
lines changed

packages/dds/tree/src/tableSchema.ts

Lines changed: 47 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License.
44
*/
55

6-
import { assert, fail } from "@fluidframework/core-utils/internal";
6+
import { fail } from "@fluidframework/core-utils/internal";
77
import { UsageError } from "@fluidframework/telemetry-utils/internal";
88

99
import { Tree, TreeAlpha } from "./shared-tree/index.js";
@@ -752,51 +752,38 @@ export namespace System_TableSchema {
752752
});
753753
return removedColumns ?? fail("Transaction did not complete.");
754754
} else {
755-
const columnsToRemove = indexOrColumns;
756-
757755
// If there are no columns to remove, do nothing
758-
if (columnsToRemove.length === 0) {
756+
if (indexOrColumns.length === 0) {
759757
return [];
760758
}
761759

762-
// Ensure the specified columns exists before starting transaction.
763-
// Improves user-facing error experience.
764-
for (const columnToRemove of columnsToRemove) {
765-
this._assertContainsColumn(columnToRemove);
760+
// Resolve any IDs to actual nodes.
761+
// This validates that all of the rows exist before starting transaction.
762+
// This improves user-facing error experience.
763+
const columnsToRemove: ColumnValueType[] = [];
764+
for (const columnOrIdToRemove of indexOrColumns) {
765+
columnsToRemove.push(this._getColumn(columnOrIdToRemove));
766766
}
767767

768-
const removedColumns: ColumnValueType[] = [];
769768
this._applyEditsInBatch(() => {
770769
// Note, throwing an error within a transaction will abort the entire transaction.
771770
// So if we throw an error here for any column, no columns will be removed.
772771
for (const columnToRemove of columnsToRemove) {
773-
const removedColumn = this._removeColumn(columnToRemove);
774-
removedColumns.push(removedColumn);
772+
// Remove the corresponding cell from all rows.
773+
for (const row of this.rows) {
774+
// TypeScript is unable to narrow the row type correctly here, hence the cast.
775+
// See: https://github.com/microsoft/TypeScript/issues/52144
776+
(row as RowValueType).removeCell(columnToRemove);
777+
}
778+
779+
// We have already validated that all of the columns exist above, so this is safe.
780+
this.columns.removeAt(this.columns.indexOf(columnToRemove));
775781
}
776782
});
777-
return removedColumns;
783+
return columnsToRemove;
778784
}
779785
}
780786

781-
private _removeColumn(columnOrId: string | ColumnValueType): ColumnValueType {
782-
const column = this._getColumn(columnOrId);
783-
const index = this.columns.indexOf(column);
784-
assert(index !== -1, "Column should exist");
785-
786-
this._applyEditsInBatch(() => {
787-
// Remove the corresponding cell from all rows.
788-
for (const row of this.rows) {
789-
// TypeScript is unable to narrow the row type correctly here, hence the cast.
790-
// See: https://github.com/microsoft/TypeScript/issues/52144
791-
(row as RowValueType).removeCell(column);
792-
}
793-
794-
this.columns.removeAt(index);
795-
});
796-
797-
return column;
798-
}
799-
800787
public removeRows(
801788
indexOrRows: number | undefined | readonly string[] | readonly RowValueType[],
802789
count?: number | undefined,
@@ -819,39 +806,28 @@ export namespace System_TableSchema {
819806
);
820807
}
821808

822-
const rowsToRemove = indexOrRows;
823-
824809
// If there are no rows to remove, do nothing
825-
if (rowsToRemove.length === 0) {
810+
if (indexOrRows.length === 0) {
826811
return [];
827812
}
828813

829-
// Ensure the specified rows exists before starting transaction.
830-
// Improves user-facing error experience.
831-
for (const rowToRemove of rowsToRemove) {
832-
this._assertContainsRow(rowToRemove);
814+
// Resolve any IDs to actual nodes.
815+
// This validates that all of the rows exist before starting transaction.
816+
// This improves user-facing error experience.
817+
const rowsToRemove: RowValueType[] = [];
818+
for (const rowToRemove of indexOrRows) {
819+
rowsToRemove.push(this._getRow(rowToRemove));
833820
}
834821

835-
const removedRows: RowValueType[] = [];
836822
this._applyEditsInBatch(() => {
837823
// Note, throwing an error within a transaction will abort the entire transaction.
838824
// So if we throw an error here for any row, no rows will be removed.
839825
for (const rowToRemove of rowsToRemove) {
840-
const removedRow = this._removeRow(rowToRemove);
841-
removedRows.push(removedRow);
826+
// We have already validated that all of the rows exist above, so this is safe.
827+
this.rows.removeAt(this.rows.indexOf(rowToRemove));
842828
}
843829
});
844-
return removedRows;
845-
}
846-
847-
private _removeRow(rowOrId: string | RowValueType): RowValueType {
848-
const rowToRemove = this._getRow(rowOrId);
849-
850-
const index = this.rows.indexOf(rowToRemove);
851-
assert(index !== -1, "Row should exist");
852-
853-
this.rows.removeAt(index);
854-
return rowToRemove;
830+
return rowsToRemove;
855831
}
856832

857833
public removeCell(
@@ -928,24 +904,24 @@ export namespace System_TableSchema {
928904
}
929905

930906
/**
931-
* Attempts to resolve a Column node or ID to a Column node.
932-
* If a node is provided, it is returned as-is.
933-
* If an ID is provided, we check the table for the corresponding Column node and return it if it exists, otherwise undefined.
907+
* Attempts to resolve the provided Column node or ID to a Column node in the table.
908+
* Returns `undefined` if there is no match.
909+
* @remarks Searches for a match based strictly on the ID and returns that result.
934910
*/
935911
private _tryGetColumn(
936912
columnOrId: string | ColumnValueType,
937913
): ColumnValueType | undefined {
938-
return typeof columnOrId === "string" ? this.getColumn(columnOrId) : columnOrId;
914+
const columnId = this._getColumnId(columnOrId);
915+
return this.getColumn(columnId);
939916
}
940917

941918
/**
942-
* Attempts to resolve a Column node or ID to a Column node.
943-
* If a node is provided, it is returned as-is.
944-
* If an ID is provided, we check the table for the corresponding Column node and return it if it exists, otherwise we throw an exception.
919+
* Attempts to resolve the provided Column node or ID to a Column node in the table.
920+
* @throws Throws a `UsageError` if there is no match.
921+
* @remarks Searches for a match based strictly on the ID and returns that result.
945922
*/
946923
private _getColumn(columnOrId: string | ColumnValueType): ColumnValueType {
947-
const column =
948-
typeof columnOrId === "string" ? this.getColumn(columnOrId) : columnOrId;
924+
const column = this._tryGetColumn(columnOrId);
949925
if (column === undefined) {
950926
this._throwMissingColumnError(this._getColumnId(columnOrId));
951927
}
@@ -961,36 +937,11 @@ export namespace System_TableSchema {
961937
return typeof columnOrId === "string" ? columnOrId : columnOrId.id;
962938
}
963939

964-
/**
965-
* Attempts to resolve a Column node or ID to its index in the table.
966-
* Returns undefined if the Column does not exist in the table.
967-
*/
968-
private _getColumnIndex(columnOrId: string | ColumnValueType): number | undefined {
969-
const column = this._tryGetColumn(columnOrId);
970-
if (column === undefined) {
971-
return undefined;
972-
}
973-
974-
const index = this.columns.indexOf(column);
975-
return index === -1 ? undefined : index;
976-
}
977-
978940
/**
979941
* Checks if a Column with the specified ID exists in the table.
980942
*/
981943
private _containsColumnWithId(columnId: string): boolean {
982-
return this._getColumnIndex(columnId) !== undefined;
983-
}
984-
985-
/**
986-
* Assert that the provided Column exists in the table.
987-
* @throws Throws a `UsageError` if the Column does not exist.
988-
*/
989-
private _assertContainsColumn(columnOrId: ColumnValueType | string): void {
990-
const columnId = this._getColumnId(columnOrId);
991-
if (!this._containsColumnWithId(columnId)) {
992-
this._throwMissingColumnError(columnId);
993-
}
944+
return this._tryGetColumn(columnId) !== undefined;
994945
}
995946

996947
/**
@@ -1001,21 +952,22 @@ export namespace System_TableSchema {
1001952
}
1002953

1003954
/**
1004-
* Attempts to resolve a Row node or ID to a Row node.
1005-
* If a node is provided, it is returned as-is.
1006-
* If an ID is provided, we check the table for the corresponding Row node and return it if it exists, otherwise undefined.
955+
* Attempts to resolve the provided Row node or ID to a Row node in the table.
956+
* Returns `undefined` if there is no match.
957+
* @remarks Searches for a match based strictly on the ID and returns that result.
1007958
*/
1008959
private _tryGetRow(rowOrId: string | RowValueType): RowValueType | undefined {
1009-
return typeof rowOrId === "string" ? this.getRow(rowOrId) : rowOrId;
960+
const rowId = this._getRowId(rowOrId);
961+
return this.getRow(rowId);
1010962
}
1011963

1012964
/**
1013-
* Attempts to resolve a Row node or ID to a Row node.
1014-
* If a node is provided, it is returned as-is.
1015-
* If an ID is provided, we check the table for the corresponding Row node and return it if it exists, otherwise we throw an exception.
965+
* Attempts to resolve the provided Row node or ID to a Row node in the table.
966+
* @throws Throws a `UsageError` if there is no match.
967+
* @remarks Searches for a match based strictly on the ID and returns that result.
1016968
*/
1017969
private _getRow(rowOrId: string | RowValueType): RowValueType {
1018-
const row = typeof rowOrId === "string" ? this.getRow(rowOrId) : rowOrId;
970+
const row = this._tryGetRow(rowOrId);
1019971
if (row === undefined) {
1020972
this._throwMissingRowError(this._getRowId(rowOrId));
1021973
}
@@ -1031,37 +983,6 @@ export namespace System_TableSchema {
1031983
return typeof rowOrId === "string" ? rowOrId : rowOrId.id;
1032984
}
1033985

1034-
/**
1035-
* Attempts to resolve a Row node or ID to its index in the table.
1036-
* Returns undefined if the Row does not exist in the table.
1037-
*/
1038-
private _getRowIndex(rowOrId: string | RowValueType): number | undefined {
1039-
const row = this._tryGetRow(rowOrId);
1040-
if (row === undefined) {
1041-
return undefined;
1042-
}
1043-
const index = this.rows.indexOf(row);
1044-
return index === -1 ? undefined : index;
1045-
}
1046-
1047-
/**
1048-
* Checks if a Column with the specified ID exists in the table.
1049-
*/
1050-
private _containsRowWithId(rowId: string): boolean {
1051-
return this._getRowIndex(rowId) !== undefined;
1052-
}
1053-
1054-
/**
1055-
* Assert that the provided Row exists in the table.
1056-
* @throws Throws a `UsageError` if the Row does not exist.
1057-
*/
1058-
private _assertContainsRow(rowOrId: RowValueType | string): void {
1059-
const rowId = this._getRowId(rowOrId);
1060-
if (!this._containsRowWithId(rowId)) {
1061-
this._throwMissingRowError(rowId);
1062-
}
1063-
}
1064-
1065986
/**
1066987
* Throw a `UsageError` for a missing Row by its ID.
1067988
*/

0 commit comments

Comments
 (0)