pipework 0.260.0 → 0.260.1
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.
- package/CHANGELOG.md +4 -0
- package/dist/request/context/guard.d.ts +1 -1
- package/dist/request/context/guard.d.ts.map +1 -1
- package/dist/request/context/guard.js +4 -2
- package/dist/request/context/guard.js.map +1 -1
- package/dist/request/context/run-in-transaction.d.ts +3 -0
- package/dist/request/context/run-in-transaction.d.ts.map +1 -1
- package/dist/request/context/run-in-transaction.js +10 -3
- package/dist/request/context/run-in-transaction.js.map +1 -1
- package/dist/request/context/types.d.ts +2 -0
- package/dist/request/context/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/request/context/guard.ts +5 -1
- package/src/request/context/run-in-transaction.ts +10 -3
- package/src/request/context/types.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.260.1
|
|
4
|
+
|
|
5
|
+
- **Fixed: an aborted `executeInTransaction` no longer commits when its transaction was idle at the abort** (#914). Aborting only cancelled a running query, so a handler awaiting a timer or an HTTP call resumed and committed. Now, when the run returns after its signal aborted, every transaction rolls back and the run rejects with `signal.reason`; `pipe()` refuses a statement on the aborted transaction with the same reason. Covers `jobs.execute(…, { signal })` and `checkpoint`.
|
|
6
|
+
|
|
3
7
|
## 0.260.0
|
|
4
8
|
|
|
5
9
|
- **Added: `idempotentRetry` retries transient socket faults on reads** (#912). `idempotentRetry.fetch(input, init, opts)` (GET, HEAD, OPTIONS only) retries the connect faults plus `UND_ERR_SOCKET` / `SocketError` ("other side closed"), `ECONNRESET`, `EPIPE` and `ETIMEDOUT`, three tries (250 ms, then 1 s); the body is read inside each try and returned buffered, so a fault mid-body is retried too. `idempotentRetry.call(send)` applies the same rule to any read the caller declares idempotent; `isTransientFault(err)` exposes the test. Never retried: a response of any status, a decode error, the caller's abort or timeout; the last fault is thrown unchanged. `connectRetry` is unchanged.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Flow, BoundTransaction } from './types.js';
|
|
2
2
|
import type { DB } from '../../data/db/index.js';
|
|
3
3
|
export declare function verifyTransactionBinding(ctx: Flow, bound: BoundTransaction, dbName: string): void;
|
|
4
|
-
export declare function bindTransaction(ctx: Flow, dbName: string, drizzle: DB): BoundTransaction;
|
|
4
|
+
export declare function bindTransaction(ctx: Flow, dbName: string, drizzle: DB, signal?: AbortSignal): BoundTransaction;
|
|
5
5
|
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/request/context/guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAA;AAGhD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,MAAM,GACb,IAAI,
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/request/context/guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAA;AAGhD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,MAAM,GACb,IAAI,CAkCN;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,IAAI,EACT,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,EAAE,EACX,MAAM,CAAC,EAAE,WAAW,GACnB,gBAAgB,CAGlB"}
|
|
@@ -28,8 +28,10 @@ export function verifyTransactionBinding(ctx, bound, dbName) {
|
|
|
28
28
|
requestId: ctx.requestId,
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
+
bound.signal?.throwIfAborted();
|
|
31
32
|
}
|
|
32
|
-
export function bindTransaction(ctx, dbName, drizzle) {
|
|
33
|
-
|
|
33
|
+
export function bindTransaction(ctx, dbName, drizzle, signal) {
|
|
34
|
+
const bound = { drizzle, nonce: ctx._nonce, tenant: ctx.tenant };
|
|
35
|
+
return signal === undefined ? bound : { ...bound, signal };
|
|
34
36
|
}
|
|
35
37
|
//# sourceMappingURL=guard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/request/context/guard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAE/D,MAAM,UAAU,wBAAwB,CACtC,GAAS,EACT,KAAuB,EACvB,MAAc;IAEd,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,IAAI,kBAAkB,CAAC,wBAAwB,EAAE;YACrD,OAAO,EACL,iCAAiC,MAAM,iDAAiD;gBACxF,2FAA2F;gBAC3F,uFAAuF;YACzF,gBAAgB,EAAE,KAAK,CAAC,KAAK;YAC7B,YAAY,EAAE,GAAG,CAAC,MAAM;YACxB,QAAQ,EAAE,MAAM;YAChB,aAAa,EAAE,GAAG,CAAC,MAAM;YACzB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,IAAI,kBAAkB,CAAC,yBAAyB,EAAE;YACtD,OAAO,EACL,iCAAiC,MAAM,6BAA6B,KAAK,CAAC,MAAM,IAAI;gBACpF,uCAAuC,GAAG,CAAC,MAAM,yCAAyC;gBAC1F,qEAAqE;gBACrE,yEAAyE;gBACzE,4DAA4D;gBAC5D,kFAAkF;gBAClF,uDAAuD;gBACvD,QAAQ;YACV,iBAAiB,EAAE,KAAK,CAAC,MAAM;YAC/B,aAAa,EAAE,GAAG,CAAC,MAAM;YACzB,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAA;IACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/request/context/guard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAE/D,MAAM,UAAU,wBAAwB,CACtC,GAAS,EACT,KAAuB,EACvB,MAAc;IAEd,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,IAAI,kBAAkB,CAAC,wBAAwB,EAAE;YACrD,OAAO,EACL,iCAAiC,MAAM,iDAAiD;gBACxF,2FAA2F;gBAC3F,uFAAuF;YACzF,gBAAgB,EAAE,KAAK,CAAC,KAAK;YAC7B,YAAY,EAAE,GAAG,CAAC,MAAM;YACxB,QAAQ,EAAE,MAAM;YAChB,aAAa,EAAE,GAAG,CAAC,MAAM;YACzB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,IAAI,kBAAkB,CAAC,yBAAyB,EAAE;YACtD,OAAO,EACL,iCAAiC,MAAM,6BAA6B,KAAK,CAAC,MAAM,IAAI;gBACpF,uCAAuC,GAAG,CAAC,MAAM,yCAAyC;gBAC1F,qEAAqE;gBACrE,yEAAyE;gBACzE,4DAA4D;gBAC5D,kFAAkF;gBAClF,uDAAuD;gBACvD,QAAQ;YACV,iBAAiB,EAAE,KAAK,CAAC,MAAM;YAC/B,aAAa,EAAE,GAAG,CAAC,MAAM;YACzB,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,CAAA;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,GAAS,EACT,MAAc,EACd,OAAW,EACX,MAAoB;IAEpB,MAAM,KAAK,GAAqB,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAA;IAClF,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,CAAA;AAC5D,CAAC"}
|
|
@@ -15,6 +15,9 @@ import type { TenantConfig } from '../../auth/tenant/types.js';
|
|
|
15
15
|
* With a `signal`, aborting cancels each transaction's in-flight query on the
|
|
16
16
|
* server (`pg_cancel_backend`), so the query fails, the transaction rolls back
|
|
17
17
|
* and the connection returns to the pool instead of being held to completion.
|
|
18
|
+
* Aborting also rolls back a transaction that was idle at the abort: the run
|
|
19
|
+
* rejects with `signal.reason` instead of committing, and `pipe()` refuses the
|
|
20
|
+
* aborted transaction.
|
|
18
21
|
*/
|
|
19
22
|
export declare function executeInTransaction<T>(ctx: Flow, databases: readonly string[], tenant: TenantConfig | null, timeoutMs: number, run: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
20
23
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-in-transaction.d.ts","sourceRoot":"","sources":["../../../src/request/context/run-in-transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,EAAE,EAAqB,MAAM,wBAAwB,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,4BAA4B,CAAA;AAM7E
|
|
1
|
+
{"version":3,"file":"run-in-transaction.d.ts","sourceRoot":"","sources":["../../../src/request/context/run-in-transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,EAAE,EAAqB,MAAM,wBAAwB,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,4BAA4B,CAAA;AAM7E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,MAAM,EAAE,YAAY,GAAG,IAAI,EAC3B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACrB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,CAAC,CAAC,CAyGZ;AAoCD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,EAAE,EACN,GAAG,EAAE,IAAI,EACT,MAAM,EAAE,YAAY,GAAG,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuBf"}
|
|
@@ -16,6 +16,9 @@ import { runInContext } from './store.js';
|
|
|
16
16
|
* With a `signal`, aborting cancels each transaction's in-flight query on the
|
|
17
17
|
* server (`pg_cancel_backend`), so the query fails, the transaction rolls back
|
|
18
18
|
* and the connection returns to the pool instead of being held to completion.
|
|
19
|
+
* Aborting also rolls back a transaction that was idle at the abort: the run
|
|
20
|
+
* rejects with `signal.reason` instead of committing, and `pipe()` refuses the
|
|
21
|
+
* aborted transaction.
|
|
19
22
|
*/
|
|
20
23
|
export async function executeInTransaction(ctx, databases, tenant, timeoutMs, run, signal) {
|
|
21
24
|
const instance = ctx.instance;
|
|
@@ -28,11 +31,14 @@ export async function executeInTransaction(ctx, databases, tenant, timeoutMs, ru
|
|
|
28
31
|
...ctx,
|
|
29
32
|
transactions: new Map(ctx.transactions),
|
|
30
33
|
};
|
|
31
|
-
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx));
|
|
34
|
+
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx, signal));
|
|
32
35
|
await propagateLocals(tx, ctx, tenant);
|
|
33
36
|
const disarm = await armCancellation(conn, tx, signal);
|
|
34
37
|
try {
|
|
35
|
-
|
|
38
|
+
const result = await runInContext(childCtx, run);
|
|
39
|
+
// Idle at the abort, nothing failed: throwing here rolls back instead of committing.
|
|
40
|
+
signal?.throwIfAborted();
|
|
41
|
+
return result;
|
|
36
42
|
}
|
|
37
43
|
finally {
|
|
38
44
|
disarm();
|
|
@@ -61,7 +67,7 @@ export async function executeInTransaction(ctx, databases, tenant, timeoutMs, ru
|
|
|
61
67
|
let signalReady;
|
|
62
68
|
readyPromises.push(new Promise(r => { signalReady = r; }));
|
|
63
69
|
txPromises.push(conn.drizzle.transaction(async (tx) => {
|
|
64
|
-
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx));
|
|
70
|
+
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx, signal));
|
|
65
71
|
await propagateLocals(tx, ctx, tenant);
|
|
66
72
|
disarms.push(await armCancellation(conn, tx, signal));
|
|
67
73
|
readyDatabases.add(dbName);
|
|
@@ -93,6 +99,7 @@ export async function executeInTransaction(ctx, databases, tenant, timeoutMs, ru
|
|
|
93
99
|
}
|
|
94
100
|
try {
|
|
95
101
|
const result = await runInContext(childCtx, run);
|
|
102
|
+
signal?.throwIfAborted();
|
|
96
103
|
releaseAll();
|
|
97
104
|
await Promise.all(txPromises);
|
|
98
105
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-in-transaction.js","sourceRoot":"","sources":["../../../src/request/context/run-in-transaction.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEzC
|
|
1
|
+
{"version":3,"file":"run-in-transaction.js","sourceRoot":"","sources":["../../../src/request/context/run-in-transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ export interface BoundTransaction {
|
|
|
7
7
|
readonly drizzle: DB;
|
|
8
8
|
readonly nonce: string;
|
|
9
9
|
readonly tenant: string | null;
|
|
10
|
+
/** Aborts the transaction: `pipe()` refuses it once aborted. */
|
|
11
|
+
readonly signal?: AbortSignal;
|
|
10
12
|
}
|
|
11
13
|
/** The AsyncLocalStorage context — carries requestId, auth, tenant, active transactions, and a nonce for integrity checks. */
|
|
12
14
|
export interface Flow<TAuth = unknown> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/request/context/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,+GAA+G;AAC/G,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/request/context/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,+GAA+G;AAC/G,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED,8HAA8H;AAC9H,MAAM,WAAW,IAAI,CAAC,KAAK,GAAG,OAAO;IACnC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,sHAAsH;IACtH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAA;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,0HAA0H;IAC1H,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,kFAAkF;IAClF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAA;IAC1C,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACpD,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;CACpC;AAED,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC"}
|
package/package.json
CHANGED
|
@@ -38,12 +38,16 @@ export function verifyTransactionBinding(
|
|
|
38
38
|
requestId: ctx.requestId,
|
|
39
39
|
})
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
bound.signal?.throwIfAborted()
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
export function bindTransaction(
|
|
44
46
|
ctx: Flow,
|
|
45
47
|
dbName: string,
|
|
46
48
|
drizzle: DB,
|
|
49
|
+
signal?: AbortSignal,
|
|
47
50
|
): BoundTransaction {
|
|
48
|
-
|
|
51
|
+
const bound: BoundTransaction = { drizzle, nonce: ctx._nonce, tenant: ctx.tenant }
|
|
52
|
+
return signal === undefined ? bound : { ...bound, signal }
|
|
49
53
|
}
|
|
@@ -20,6 +20,9 @@ import { runInContext } from './store.js'
|
|
|
20
20
|
* With a `signal`, aborting cancels each transaction's in-flight query on the
|
|
21
21
|
* server (`pg_cancel_backend`), so the query fails, the transaction rolls back
|
|
22
22
|
* and the connection returns to the pool instead of being held to completion.
|
|
23
|
+
* Aborting also rolls back a transaction that was idle at the abort: the run
|
|
24
|
+
* rejects with `signal.reason` instead of committing, and `pipe()` refuses the
|
|
25
|
+
* aborted transaction.
|
|
23
26
|
*/
|
|
24
27
|
export async function executeInTransaction<T>(
|
|
25
28
|
ctx: Flow,
|
|
@@ -41,13 +44,16 @@ export async function executeInTransaction<T>(
|
|
|
41
44
|
...ctx,
|
|
42
45
|
transactions: new Map(ctx.transactions),
|
|
43
46
|
}
|
|
44
|
-
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx))
|
|
47
|
+
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx, signal))
|
|
45
48
|
|
|
46
49
|
await propagateLocals(tx, ctx, tenant)
|
|
47
50
|
|
|
48
51
|
const disarm = await armCancellation(conn, tx, signal)
|
|
49
52
|
try {
|
|
50
|
-
|
|
53
|
+
const result = await runInContext(childCtx, run)
|
|
54
|
+
// Idle at the abort, nothing failed: throwing here rolls back instead of committing.
|
|
55
|
+
signal?.throwIfAborted()
|
|
56
|
+
return result
|
|
51
57
|
} finally {
|
|
52
58
|
disarm()
|
|
53
59
|
}
|
|
@@ -82,7 +88,7 @@ export async function executeInTransaction<T>(
|
|
|
82
88
|
|
|
83
89
|
txPromises.push(
|
|
84
90
|
conn.drizzle.transaction(async (tx) => {
|
|
85
|
-
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx))
|
|
91
|
+
childCtx.transactions.set(dbName, bindTransaction(ctx, dbName, tx, signal))
|
|
86
92
|
await propagateLocals(tx, ctx, tenant)
|
|
87
93
|
disarms.push(await armCancellation(conn, tx, signal))
|
|
88
94
|
readyDatabases.add(dbName)
|
|
@@ -119,6 +125,7 @@ export async function executeInTransaction<T>(
|
|
|
119
125
|
|
|
120
126
|
try {
|
|
121
127
|
const result = await runInContext(childCtx, run)
|
|
128
|
+
signal?.throwIfAborted()
|
|
122
129
|
releaseAll()
|
|
123
130
|
await Promise.all(txPromises)
|
|
124
131
|
return result
|
|
@@ -8,6 +8,8 @@ export interface BoundTransaction {
|
|
|
8
8
|
readonly drizzle: DB
|
|
9
9
|
readonly nonce: string
|
|
10
10
|
readonly tenant: string | null
|
|
11
|
+
/** Aborts the transaction: `pipe()` refuses it once aborted. */
|
|
12
|
+
readonly signal?: AbortSignal
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
/** The AsyncLocalStorage context — carries requestId, auth, tenant, active transactions, and a nonce for integrity checks. */
|