From a3e21b62dd4c49370f544429cecab20e8a6d2d32 Mon Sep 17 00:00:00 2001 From: Antony Rizzitelli Date: Mon, 14 Sep 2026 13:25:51 +0000 Subject: [PATCH 1/3] feat(transactions): add optional transaction interface --- package.json | 7 +++++++ src/transactions.ts | 9 +++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/transactions.ts 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..c1d8c88 --- /dev/null +++ b/src/transactions.ts @@ -0,0 +1,9 @@ +import { InterfaceFunction } from "@antelopejs/interface-core"; + +/** + * Runs a callback once inside an atomic database transaction. + * + * The returned promise resolves after commit. Rejections abort the transaction. + */ +export const RunInTransaction = + InterfaceFunction<(callback: () => Promise) => Promise>(); From 146edb31264d00326e79e20e131453ec677b66dd Mon Sep 17 00:00:00 2001 From: Antony Rizzitelli Date: Mon, 14 Sep 2026 13:34:27 +0000 Subject: [PATCH 2/3] docs(transactions): clarify execution guarantees --- src/transactions.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/transactions.ts b/src/transactions.ts index c1d8c88..d301c1a 100644 --- a/src/transactions.ts +++ b/src/transactions.ts @@ -3,7 +3,24 @@ import { InterfaceFunction } from "@antelopejs/interface-core"; /** * Runs a callback once inside an atomic database transaction. * - * The returned promise resolves after commit. Rejections abort the 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<(callback: () => Promise) => Promise>(); From 458617fd4fee555e434d64591fec2f5be79188a1 Mon Sep 17 00:00:00 2001 From: Antony Rizzitelli Date: Mon, 14 Sep 2026 14:49:45 +0000 Subject: [PATCH 3/3] fix(transactions): preserve callback result inference --- src/transactions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/transactions.ts b/src/transactions.ts index d301c1a..a780c13 100644 --- a/src/transactions.ts +++ b/src/transactions.ts @@ -1,5 +1,7 @@ import { InterfaceFunction } from "@antelopejs/interface-core"; +type TransactionRunner = (callback: () => Promise) => Promise; + /** * Runs a callback once inside an atomic database transaction. * @@ -23,4 +25,4 @@ import { InterfaceFunction } from "@antelopejs/interface-core"; * @returns The callback result after the transaction is committed */ export const RunInTransaction = - InterfaceFunction<(callback: () => Promise) => Promise>(); + InterfaceFunction() as TransactionRunner;