diff --git a/package.json b/package.json index 3c6bdcc..f8c80d4 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,9 @@ "stream": [ "dist/stream.d.ts" ], + "transactions": [ + "dist/transactions.d.ts" + ], "valueproxy": [ "dist/valueproxy.d.ts" ] @@ -73,6 +76,10 @@ "types": "./dist/stream.d.ts", "default": "./dist/stream.js" }, + "./transactions": { + "types": "./dist/transactions.d.ts", + "default": "./dist/transactions.js" + }, "./valueproxy": { "types": "./dist/valueproxy.d.ts", "default": "./dist/valueproxy.js" diff --git a/src/transactions.ts b/src/transactions.ts new file mode 100644 index 0000000..a780c13 --- /dev/null +++ b/src/transactions.ts @@ -0,0 +1,28 @@ +import { InterfaceFunction } from "@antelopejs/interface-core"; + +type TransactionRunner = (callback: () => Promise) => Promise; + +/** + * Runs a callback once inside an atomic database transaction. + * + * The callback is invoked exactly once. Database operations started through the + * interface during the callback share the transaction. The returned promise + * resolves only after commit, while callback rejections abort the transaction. + * + * Do not perform externally visible side effects in the callback because a + * database rollback cannot undo them. Nested transactions and database work + * started in the callback but awaited after it returns are rejected. Providers + * reject this operation when their configured topology does not support + * transactions. + * + * A rejection while committing can have an ambiguous outcome: the provider may + * be unable to determine whether the database committed the transaction. The + * callback is never replayed to resolve uncertain commit acknowledgement. + * + * Transaction duration and commit acknowledgement bounds are provider-specific. + * + * @param callback Asynchronous database work to execute atomically + * @returns The callback result after the transaction is committed + */ +export const RunInTransaction = + InterfaceFunction() as TransactionRunner;