Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/dds/tree/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ export {
type NodeInDocumentConstraint,
type NoChangeConstraint,
type RunTransactionParams,
type RunTransactionAsyncParams,
type RunTransactionSyncParams,
type VoidTransactionCallbackStatus,
type TransactionCallbackStatus,
type TransactionResult,
Expand Down
15 changes: 8 additions & 7 deletions packages/dds/tree/src/shared-tree/schematizingTreeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ import {
type TransactionCallbackStatus,
type TransactionResult,
type TransactionResultExt,
type RunTransactionParams,
type RunTransactionAsyncParams,
type RunTransactionSyncParams,
HydratedContext,
SimpleContextSlot,
areImplicitFieldSchemaEqual,
Expand Down Expand Up @@ -273,38 +274,38 @@ export class SchematizingSimpleTreeView<

public runTransaction<TSuccessValue, TFailureValue>(
transaction: () => TransactionCallbackStatus<TSuccessValue, TFailureValue>,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResultExt<TSuccessValue, TFailureValue>;
public runTransaction(
transaction: () => VoidTransactionCallbackStatus | void,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResult;
public runTransaction<TSuccessValue, TFailureValue>(
transaction: () =>
| TransactionCallbackStatus<TSuccessValue, TFailureValue>
| VoidTransactionCallbackStatus
| void,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResultExt<TSuccessValue, TFailureValue> | TransactionResult {
this.ensureUndisposed();
return this.checkout.runTransaction(transaction, params);
}

public runTransactionAsync<TSuccessValue, TFailureValue>(
transaction: () => Promise<TransactionCallbackStatus<TSuccessValue, TFailureValue>>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResultExt<TSuccessValue, TFailureValue>>;
public runTransactionAsync(
transaction: () => Promise<VoidTransactionCallbackStatus | void>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResult>;
public async runTransactionAsync<TSuccessValue, TFailureValue>(
transaction: () => Promise<
| TransactionCallbackStatus<TSuccessValue, TFailureValue>
| VoidTransactionCallbackStatus
| void
>,
params: RunTransactionParams | undefined,
params: RunTransactionAsyncParams | undefined,
): Promise<TransactionResultExt<TSuccessValue, TFailureValue> | TransactionResult> {
this.ensureUndisposed();
if (this.checkout.transaction.size > 0) {
Expand Down
32 changes: 23 additions & 9 deletions packages/dds/tree/src/shared-tree/treeCheckout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,16 @@ import {
type TransactionResult,
type TransactionResultExt,
type RunTransactionParams,
type RunTransactionAsyncParams,
type RunTransactionSyncParams,
type TransactionConstraintAlpha,
type TreeViewAlpha,
getInnerNode,
getKernel,
customFromCursorStored,
type CustomTreeValue,
type CustomTreeNode,
withBufferedTreeEvents,
} from "../simple-tree/index.js";
import {
Breakable,
Expand Down Expand Up @@ -845,32 +848,43 @@ export class TreeCheckout implements ITreeCheckout {

public runTransaction<TSuccessValue, TFailureValue>(
transaction: () => TransactionCallbackStatus<TSuccessValue, TFailureValue>,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResultExt<TSuccessValue, TFailureValue>;
public runTransaction(
transaction: () => VoidTransactionCallbackStatus | void,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResult;
@breakingMethod
public runTransaction<TSuccessValue, TFailureValue>(
transaction: () =>
| TransactionCallbackStatus<TSuccessValue, TFailureValue>
| VoidTransactionCallbackStatus
| void,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResultExt<TSuccessValue, TFailureValue> | TransactionResult {
this.mountTransaction(params, false);
const transactionCallbackStatus = transaction();
return this.unmountTransaction(transactionCallbackStatus, params);
const transactionCore = ():
| TransactionResultExt<TSuccessValue, TFailureValue>
| TransactionResult => {
this.mountTransaction(params, false);
const transactionCallbackStatus = transaction();
return this.unmountTransaction(transactionCallbackStatus, params);
};
return params?.deferEvents === true
? withBufferedTreeEvents(transactionCore, {
// On rollback the tree is restored to its starting state, so any buffered events
// represent net-zero changes and must not be surfaced to listeners.
shouldDiscard: (result) => !result.success,
})
: transactionCore();
}

public runTransactionAsync<TSuccessValue, TFailureValue>(
transaction: () => Promise<TransactionCallbackStatus<TSuccessValue, TFailureValue>>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResultExt<TSuccessValue, TFailureValue>>;
public runTransactionAsync(
transaction: () => Promise<VoidTransactionCallbackStatus | void>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResult>;
@breakingMethod
public async runTransactionAsync<TSuccessValue, TFailureValue>(
Expand All @@ -879,7 +893,7 @@ export class TreeCheckout implements ITreeCheckout {
| VoidTransactionCallbackStatus
| void
>,
params: RunTransactionParams | undefined,
params: RunTransactionAsyncParams | undefined,
): Promise<TransactionResultExt<TSuccessValue, TFailureValue> | TransactionResult> {
this.mountTransaction(params, true);
const transactionCallbackStatus = await transaction();
Expand Down
2 changes: 2 additions & 0 deletions packages/dds/tree/src/simple-tree/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ export {
type NodeInDocumentConstraint,
type NoChangeConstraint,
type RunTransactionParams,
type RunTransactionAsyncParams,
type RunTransactionSyncParams,
type VoidTransactionCallbackStatus,
type TransactionCallbackStatus,
type TransactionResult,
Expand Down
26 changes: 26 additions & 0 deletions packages/dds/tree/src/simple-tree/api/transactionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export interface RunTransactionParams {
* If any of the constraints are not met after the transaction has been ordered by the service, it will be rolled back on this client and ignored by all other clients.
*/
readonly preconditions?: readonly TransactionConstraintAlpha[];

/**
* A label for this transaction that allows it to be correlated with later edits (e.g. for controlling undo/redo grouping).
* @remarks
Expand All @@ -147,3 +148,28 @@ export interface RunTransactionParams {
*/
readonly label?: unknown;
}

/**
* The parameters for the asynchronous {@link RunTransaction | runTransaction} API.
* @input
* @alpha
*/
export interface RunTransactionAsyncParams extends RunTransactionParams {}

/**
* The parameters for the synchronous {@link RunTransaction | runTransaction} API.
* @input
* @alpha
*/
export interface RunTransactionSyncParams extends RunTransactionParams {
/**
* Set this to true to have the transaction's change events buffered and emitted only once the transaction completes.
*
* @remarks
* If the transaction rolls back *during the transaction*, no buffered events are emitted (the tree is unchanged).
* This does not apply to a later rollbacks (e.g. caused by post-sequencing constraint validation after `runTransaction` has returned).
*
* @defaultValue `false`
*/
readonly deferEvents?: boolean;
Comment thread
Josmithr marked this conversation as resolved.
}
24 changes: 14 additions & 10 deletions packages/dds/tree/src/simple-tree/api/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import type { UnsafeUnknownSchema } from "../unsafeUnknownSchema.js";

import type { TreeViewConfiguration } from "./configuration.js";
import type {
RunTransactionParams,
RunTransactionAsyncParams,
RunTransactionSyncParams,
TransactionCallbackStatus,
TransactionResult,
TransactionResultExt,
Expand Down Expand Up @@ -193,7 +194,7 @@ export interface TreeContextAlpha {
* Run a synchronous transaction which groups sequential edits to the tree into a single atomic edit if possible.
* @param transaction - A callback run during the transaction to perform user-supplied operations.
* It may optionally return a {@link WithValue | value }, which will be returned by the `runTransaction` call.
* @param params - Optional {@link RunTransactionParams | parameters} for the transaction.
* @param params - Optional {@link RunTransactionSyncParams | parameters} for the transaction.
* @returns A {@link TransactionResultExt | value } indicating whether or not the transaction succeeded, and containing the value returned by `transaction`.
* @remarks
* All of the changes in the transaction are applied synchronously and therefore no other changes from a remote client can be interleaved with those changes.
Expand All @@ -215,11 +216,14 @@ export interface TreeContextAlpha {
*/
runTransaction<TValue>(
transaction: () => WithValue<TValue>,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResultExt<TValue, TValue>;

/** An overload of {@link TreeContextAlpha.(runTransaction:1) | runTransaction } which does not return a value. */
runTransaction(transaction: () => void, params?: RunTransactionParams): TransactionResult;
runTransaction(
transaction: () => void,
params?: RunTransactionSyncParams,
): TransactionResult;

/**
* An asynchronous version of {@link TreeContextAlpha.(runTransaction:1) | runTransaction}.
Expand All @@ -234,13 +238,13 @@ export interface TreeContextAlpha {
*/
runTransactionAsync<TValue>(
transaction: () => Promise<WithValue<TValue>>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResultExt<TValue, TValue>>;

/** An overload of {@link TreeContextAlpha.(runTransactionAsync:1) | runTransactionAsync } which does not return a value. */
runTransactionAsync(
transaction: () => Promise<void>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResult>;

/**
Expand Down Expand Up @@ -301,15 +305,15 @@ export interface TreeBranchAlpha extends TreeBranch, TreeContextAlpha {
*/
runTransaction<TSuccessValue, TFailureValue>(
transaction: () => TransactionCallbackStatus<TSuccessValue, TFailureValue>,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResultExt<TSuccessValue, TFailureValue>;

/**
* An overload of {@link TreeBranchAlpha.(runTransaction:1) | runTransaction } which does not return a value.
*/
runTransaction(
transaction: () => VoidTransactionCallbackStatus | void,
params?: RunTransactionParams,
params?: RunTransactionSyncParams,
): TransactionResult;

/**
Expand All @@ -319,15 +323,15 @@ export interface TreeBranchAlpha extends TreeBranch, TreeContextAlpha {

runTransactionAsync<TSuccessValue, TFailureValue>(
transaction: () => Promise<TransactionCallbackStatus<TSuccessValue, TFailureValue>>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResultExt<TSuccessValue, TFailureValue>>;

/**
* An overload of {@link TreeBranchAlpha.(runTransactionAsync:1) | runTransactionAsync } which does not return a value.
*/
runTransactionAsync(
transaction: () => Promise<VoidTransactionCallbackStatus | void>,
params?: RunTransactionParams,
params?: RunTransactionAsyncParams,
): Promise<TransactionResult>;

/**
Expand Down
Loading
Loading