@kronos-ts/drizzle 0.2.3 → 0.3.0
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/dist/drizzle-transaction-manager.d.ts +21 -1
- package/dist/drizzle-transaction-manager.d.ts.map +1 -1
- package/dist/drizzle-transaction-manager.js +21 -2
- package/dist/drizzle-transaction-manager.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/drizzle-transaction-manager.ts +41 -1
- package/src/index.ts +1 -0
|
@@ -10,6 +10,26 @@ export interface DrizzleDatabaseLike {
|
|
|
10
10
|
* The Drizzle transaction object — has the same query API as the database.
|
|
11
11
|
*/
|
|
12
12
|
export type DrizzleTransaction = any;
|
|
13
|
+
export interface DrizzleTransactionManagerOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Runs once on every transaction, right after it opens and before the UoW
|
|
16
|
+
* gets the handle. This is where a Postgres-backed deployment arms session
|
|
17
|
+
* GUCs — chiefly `idle_in_transaction_session_timeout` — so a stalled UoW
|
|
18
|
+
* (e.g. a hung dead-letter drain whose replay never returns) is aborted by
|
|
19
|
+
* the database instead of pinning a connection indefinitely. The Postgres
|
|
20
|
+
* adapter does this for its own transactions; this hook is the equivalent
|
|
21
|
+
* seam for the (DB-agnostic) Drizzle/Knex path. No-op by default.
|
|
22
|
+
*
|
|
23
|
+
* Example (postgres-js driver):
|
|
24
|
+
* ```ts
|
|
25
|
+
* drizzleTransactionManager(db, {
|
|
26
|
+
* onBeginTransaction: (tx) => tx.execute(sql.raw(
|
|
27
|
+
* "SET LOCAL idle_in_transaction_session_timeout = 30000")),
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
readonly onBeginTransaction?: (tx: DrizzleTransaction) => Promise<void>;
|
|
32
|
+
}
|
|
13
33
|
/**
|
|
14
34
|
* Creates a TransactionManager for Drizzle ORM.
|
|
15
35
|
*
|
|
@@ -32,5 +52,5 @@ export type DrizzleTransaction = any;
|
|
|
32
52
|
* const txManager = drizzleTransactionManager(db)
|
|
33
53
|
* ```
|
|
34
54
|
*/
|
|
35
|
-
export declare function drizzleTransactionManager(db: DrizzleDatabaseLike): TransactionManager<DrizzleTransaction>;
|
|
55
|
+
export declare function drizzleTransactionManager(db: DrizzleDatabaseLike, options?: DrizzleTransactionManagerOptions): TransactionManager<DrizzleTransaction>;
|
|
36
56
|
//# sourceMappingURL=drizzle-transaction-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-transaction-manager.d.ts","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAEpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"drizzle-transaction-manager.d.ts","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAEpC,MAAM,WAAW,gCAAgC;IAC/C;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACxE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,mBAAmB,EACvB,OAAO,GAAE,gCAAqC,GAC7C,kBAAkB,CAAC,kBAAkB,CAAC,CA6DxC"}
|
|
@@ -20,23 +20,42 @@
|
|
|
20
20
|
* const txManager = drizzleTransactionManager(db)
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
export function drizzleTransactionManager(db) {
|
|
23
|
+
export function drizzleTransactionManager(db, options = {}) {
|
|
24
|
+
const { onBeginTransaction } = options;
|
|
24
25
|
return {
|
|
25
26
|
async begin() {
|
|
26
27
|
let resolveTx;
|
|
28
|
+
let rejectTx;
|
|
27
29
|
let resolveCompletion;
|
|
28
30
|
let rejectCompletion;
|
|
29
|
-
const txReady = new Promise((resolve) => {
|
|
31
|
+
const txReady = new Promise((resolve, reject) => {
|
|
30
32
|
resolveTx = resolve;
|
|
33
|
+
rejectTx = reject;
|
|
31
34
|
});
|
|
32
35
|
const completionSignal = new Promise((resolve, reject) => {
|
|
33
36
|
resolveCompletion = resolve;
|
|
34
37
|
rejectCompletion = reject;
|
|
35
38
|
});
|
|
36
39
|
const txPromise = db.transaction(async (tx) => {
|
|
40
|
+
// Arm session settings (e.g. idle-in-transaction timeout) before the
|
|
41
|
+
// UoW gets the handle, so begin() only resolves once the tx is bounded.
|
|
42
|
+
if (onBeginTransaction) {
|
|
43
|
+
try {
|
|
44
|
+
await onBeginTransaction(tx);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
// Surface as a begin() rejection rather than hanging on txReady.
|
|
48
|
+
rejectTx(err);
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
37
52
|
resolveTx(tx);
|
|
38
53
|
await completionSignal;
|
|
39
54
|
});
|
|
55
|
+
// If db.transaction() rejects before onBeginTransaction runs (e.g. the
|
|
56
|
+
// pool can't hand out a connection), make begin() reject instead of
|
|
57
|
+
// hanging on txReady forever.
|
|
58
|
+
txPromise.catch(rejectTx);
|
|
40
59
|
const tx = await txReady;
|
|
41
60
|
tx.__kronos_commit = resolveCompletion;
|
|
42
61
|
tx.__kronos_rollback = rejectCompletion;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-transaction-manager.js","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"drizzle-transaction-manager.js","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAoCA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,yBAAyB,CACvC,EAAuB,EACvB,UAA4C,EAAE;IAE9C,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAA;IACtC,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,SAA4C,CAAA;YAChD,IAAI,QAAmC,CAAA;YACvC,IAAI,iBAA8B,CAAA;YAClC,IAAI,gBAA2C,CAAA;YAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAClE,SAAS,GAAG,OAAO,CAAA;gBACnB,QAAQ,GAAG,MAAM,CAAA;YACnB,CAAC,CAAC,CAAA;YAEF,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC7D,iBAAiB,GAAG,OAAO,CAAA;gBAC3B,gBAAgB,GAAG,MAAM,CAAA;YAC3B,CAAC,CAAC,CAAA;YAEF,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBAC5C,qEAAqE;gBACrE,wEAAwE;gBACxE,IAAI,kBAAkB,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACH,MAAM,kBAAkB,CAAC,EAAE,CAAC,CAAA;oBAC9B,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,iEAAiE;wBACjE,QAAQ,CAAC,GAAG,CAAC,CAAA;wBACb,MAAM,GAAG,CAAA;oBACX,CAAC;gBACH,CAAC;gBACD,SAAS,CAAC,EAAE,CAAC,CAAA;gBACb,MAAM,gBAAgB,CAAA;YACxB,CAAC,CAAC,CAAA;YACF,uEAAuE;YACvE,oEAAoE;YACpE,8BAA8B;YAC9B,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAEzB,MAAM,EAAE,GAAG,MAAM,OAAO,CACvB;YAAC,EAAU,CAAC,eAAe,GAAG,iBAAiB,CAC/C;YAAC,EAAU,CAAC,iBAAiB,GAAG,gBAAgB,CAChD;YAAC,EAAU,CAAC,kBAAkB,GAAG,SAAS,CAAA;YAE3C,OAAO,EAAE,CAAA;QACX,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAsB;YACjC,MAAM,MAAM,GAAI,EAAU,CAAC,eAA6B,CAAA;YACxD,MAAM,SAAS,GAAI,EAAU,CAAC,kBAAmC,CAAA;YACjE,MAAM,EAAE,CAAA;YACR,MAAM,SAAS,CAAA;QACjB,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,EAAsB;YACnC,MAAM,QAAQ,GAAI,EAAU,CAAC,iBAA6C,CAAA;YAC1E,MAAM,SAAS,GAAI,EAAU,CAAC,kBAAmC,CAAA;YACjE,QAAQ,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAA;YAC9C,IAAI,CAAC;gBAAC,MAAM,SAAS,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;QAClD,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { drizzleTransactionManager, type DrizzleDatabaseLike, type DrizzleTransaction, } from "./drizzle-transaction-manager.js";
|
|
1
|
+
export { drizzleTransactionManager, type DrizzleDatabaseLike, type DrizzleTransaction, type DrizzleTransactionManagerOptions, } from "./drizzle-transaction-manager.js";
|
|
2
2
|
export { drizzleTokenStore, type DrizzleTokenStoreConfig, } from "./drizzle-token-store.js";
|
|
3
3
|
export { drizzleDeadLetterQueue, type DrizzleDeadLetterQueueConfig, } from "./drizzle-dead-letter-queue.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,gCAAgC,GACtC,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EACL,iBAAiB,EACjB,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,EACtB,KAAK,4BAA4B,GAClC,MAAM,gCAAgC,CAAA"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAI1B,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EACL,iBAAiB,GAElB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,GAEvB,MAAM,gCAAgC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kronos-ts/drizzle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Drizzle ORM extension for Kronos.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@kronos-ts/common": "0.1.1",
|
|
53
|
-
"@kronos-ts/messaging": "0.
|
|
53
|
+
"@kronos-ts/messaging": "0.8.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"drizzle-orm": ">=0.30.0"
|
|
@@ -13,6 +13,27 @@ export interface DrizzleDatabaseLike {
|
|
|
13
13
|
*/
|
|
14
14
|
export type DrizzleTransaction = any
|
|
15
15
|
|
|
16
|
+
export interface DrizzleTransactionManagerOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Runs once on every transaction, right after it opens and before the UoW
|
|
19
|
+
* gets the handle. This is where a Postgres-backed deployment arms session
|
|
20
|
+
* GUCs — chiefly `idle_in_transaction_session_timeout` — so a stalled UoW
|
|
21
|
+
* (e.g. a hung dead-letter drain whose replay never returns) is aborted by
|
|
22
|
+
* the database instead of pinning a connection indefinitely. The Postgres
|
|
23
|
+
* adapter does this for its own transactions; this hook is the equivalent
|
|
24
|
+
* seam for the (DB-agnostic) Drizzle/Knex path. No-op by default.
|
|
25
|
+
*
|
|
26
|
+
* Example (postgres-js driver):
|
|
27
|
+
* ```ts
|
|
28
|
+
* drizzleTransactionManager(db, {
|
|
29
|
+
* onBeginTransaction: (tx) => tx.execute(sql.raw(
|
|
30
|
+
* "SET LOCAL idle_in_transaction_session_timeout = 30000")),
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
readonly onBeginTransaction?: (tx: DrizzleTransaction) => Promise<void>
|
|
35
|
+
}
|
|
36
|
+
|
|
16
37
|
/**
|
|
17
38
|
* Creates a TransactionManager for Drizzle ORM.
|
|
18
39
|
*
|
|
@@ -37,15 +58,19 @@ export type DrizzleTransaction = any
|
|
|
37
58
|
*/
|
|
38
59
|
export function drizzleTransactionManager(
|
|
39
60
|
db: DrizzleDatabaseLike,
|
|
61
|
+
options: DrizzleTransactionManagerOptions = {},
|
|
40
62
|
): TransactionManager<DrizzleTransaction> {
|
|
63
|
+
const { onBeginTransaction } = options
|
|
41
64
|
return {
|
|
42
65
|
async begin(): Promise<DrizzleTransaction> {
|
|
43
66
|
let resolveTx!: (tx: DrizzleTransaction) => void
|
|
67
|
+
let rejectTx!: (error: unknown) => void
|
|
44
68
|
let resolveCompletion!: () => void
|
|
45
69
|
let rejectCompletion!: (error: unknown) => void
|
|
46
70
|
|
|
47
|
-
const txReady = new Promise<DrizzleTransaction>((resolve) => {
|
|
71
|
+
const txReady = new Promise<DrizzleTransaction>((resolve, reject) => {
|
|
48
72
|
resolveTx = resolve
|
|
73
|
+
rejectTx = reject
|
|
49
74
|
})
|
|
50
75
|
|
|
51
76
|
const completionSignal = new Promise<void>((resolve, reject) => {
|
|
@@ -54,9 +79,24 @@ export function drizzleTransactionManager(
|
|
|
54
79
|
})
|
|
55
80
|
|
|
56
81
|
const txPromise = db.transaction(async (tx) => {
|
|
82
|
+
// Arm session settings (e.g. idle-in-transaction timeout) before the
|
|
83
|
+
// UoW gets the handle, so begin() only resolves once the tx is bounded.
|
|
84
|
+
if (onBeginTransaction) {
|
|
85
|
+
try {
|
|
86
|
+
await onBeginTransaction(tx)
|
|
87
|
+
} catch (err) {
|
|
88
|
+
// Surface as a begin() rejection rather than hanging on txReady.
|
|
89
|
+
rejectTx(err)
|
|
90
|
+
throw err
|
|
91
|
+
}
|
|
92
|
+
}
|
|
57
93
|
resolveTx(tx)
|
|
58
94
|
await completionSignal
|
|
59
95
|
})
|
|
96
|
+
// If db.transaction() rejects before onBeginTransaction runs (e.g. the
|
|
97
|
+
// pool can't hand out a connection), make begin() reject instead of
|
|
98
|
+
// hanging on txReady forever.
|
|
99
|
+
txPromise.catch(rejectTx)
|
|
60
100
|
|
|
61
101
|
const tx = await txReady
|
|
62
102
|
;(tx as any).__kronos_commit = resolveCompletion
|