@fluojs/drizzle 1.0.0-beta.3 → 1.0.0-beta.5
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/README.ko.md +6 -1
- package/README.md +6 -1
- package/dist/database.d.ts +5 -0
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +120 -12
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +6 -3
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +2 -0
- package/package.json +5 -5
package/README.ko.md
CHANGED
|
@@ -107,6 +107,9 @@ class UsersController {}
|
|
|
107
107
|
### 종료와 상태 계약
|
|
108
108
|
|
|
109
109
|
`DrizzleTransactionInterceptor`는 각 HTTP 요청을 `DrizzleDatabase.requestTransaction(...)`으로 실행합니다. 애플리케이션 종료 중에는 `DrizzleDatabase`가 아직 활성 상태인 요청 트랜잭션을 abort하고, 해당 transaction callback이 settle되거나 rollback될 때까지 기다린 뒤 선택적 `dispose(database)` hook을 실행합니다. 이 순서는 pool이나 외부 관리 리소스를 닫기 전에 driver가 rollback/cleanup 작업을 끝낼 수 있게 보장합니다.
|
|
110
|
+
기존 요청 boundary 안에서 열린 중첩 `requestTransaction(...)` 호출은 활성 Drizzle transaction을 재사용하면서도 ambient request abort signal을 관찰합니다. 기존 수동 transaction boundary 안에서 열린 중첩 `requestTransaction(...)` 호출도 두 번째 Drizzle transaction을 열지 않고 shutdown settlement tracking에 참여하며, 해당 settlement handle은 바깥 수동 transaction이 settle될 때까지 tracking에 남아 shutdown이 `dispose(database)`를 실행하기 전에 그 바깥 경계까지 drain하게 합니다. 단, platform status activity count는 더 짧게 유지됩니다. 중첩 request callback이 settle되는 즉시, 바깥 수동 transaction이 계속 실행 중이어도 `details.activeRequestTransactions`는 감소합니다.
|
|
111
|
+
종료가 시작된 뒤 새 `requestTransaction(...)` 호출은 거부되므로, 종료 boundary를 지난 뒤 시작되는 늦은 요청 트랜잭션보다 dispose가 먼저 실행되는 상황을 방지합니다.
|
|
112
|
+
요청 callback이 완료된 뒤 underlying Drizzle transaction runner가 commit 또는 rollback을 끝내기 전에 request signal이 abort되면, `requestTransaction(...)`은 먼저 해당 runner가 settle될 때까지 기다린 다음 abort reason으로 reject합니다. 이 동작은 Drizzle cleanup을 request cancellation과 직렬화하면서, 완료된 callback 결과를 반환하는 대신 늦은 request abort를 caller에게 드러냅니다.
|
|
110
113
|
|
|
111
114
|
`createDrizzlePlatformStatusSnapshot(...)`과 `DrizzleDatabase.createPlatformStatusSnapshot()`은 같은 계약을 진단 surface에 노출합니다.
|
|
112
115
|
|
|
@@ -141,12 +144,14 @@ defineModule(ManualDrizzleModule, {
|
|
|
141
144
|
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
|
142
145
|
- `DrizzleDatabase`
|
|
143
146
|
- `DrizzleTransactionInterceptor`
|
|
144
|
-
- `DRIZZLE_DATABASE`, `DRIZZLE_DISPOSE`, `DRIZZLE_OPTIONS`
|
|
147
|
+
- `DRIZZLE_DATABASE`, `DRIZZLE_DISPOSE`, `DRIZZLE_HANDLE_PROVIDER`, `DRIZZLE_OPTIONS`
|
|
145
148
|
- `createDrizzlePlatformStatusSnapshot(...)`
|
|
146
149
|
- `DrizzleDatabaseLike`
|
|
147
150
|
- `DrizzleModuleOptions`
|
|
148
151
|
- `DrizzleHandleProvider`
|
|
149
152
|
|
|
153
|
+
`DRIZZLE_HANDLE_PROVIDER`는 lifecycle-aware `DrizzleDatabase` wrapper를 가리키는 alias token입니다. `@fluojs/terminus` 같은 health integration은 이 token을 통해 raw database ping으로 fallback하기 전에 `createPlatformStatusSnapshot()`을 읽습니다.
|
|
154
|
+
|
|
150
155
|
### `DrizzleModule`
|
|
151
156
|
|
|
152
157
|
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
package/README.md
CHANGED
|
@@ -107,6 +107,9 @@ class UsersController {}
|
|
|
107
107
|
### Shutdown and status contracts
|
|
108
108
|
|
|
109
109
|
`DrizzleTransactionInterceptor` runs each HTTP request through `DrizzleDatabase.requestTransaction(...)`. During application shutdown, `DrizzleDatabase` aborts any still-active request transaction, waits for its transaction callback to settle or roll back, and only then runs the optional `dispose(database)` hook. This ordering lets drivers finish rollback/cleanup work before pools or externally managed resources are closed.
|
|
110
|
+
Nested `requestTransaction(...)` calls opened inside an existing request boundary observe the ambient request abort signal while still reusing the active Drizzle transaction. Nested `requestTransaction(...)` calls opened inside an existing manual transaction boundary also join shutdown settlement tracking without opening a second Drizzle transaction, and their settlement handle remains tracked until the outer manual transaction settles so shutdown drains that outer boundary before `dispose(database)` runs. The platform status activity count is intentionally shorter lived: once the nested request callback settles, `details.activeRequestTransactions` is decremented even if the outer manual transaction continues running.
|
|
111
|
+
New `requestTransaction(...)` calls are rejected once shutdown begins, so disposal cannot overtake a late request transaction that starts after the shutdown boundary is crossed.
|
|
112
|
+
If the request signal aborts after the request callback has completed but before the underlying Drizzle transaction runner finishes committing or rolling back, `requestTransaction(...)` waits for that runner to settle first and then rejects with the abort reason. This keeps Drizzle cleanup serialized with request cancellation while making the late request abort visible to the caller instead of returning the completed callback result.
|
|
110
113
|
|
|
111
114
|
`createDrizzlePlatformStatusSnapshot(...)` and `DrizzleDatabase.createPlatformStatusSnapshot()` expose the same contract to diagnostics surfaces:
|
|
112
115
|
|
|
@@ -141,12 +144,14 @@ defineModule(ManualDrizzleModule, {
|
|
|
141
144
|
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
|
142
145
|
- `DrizzleDatabase`
|
|
143
146
|
- `DrizzleTransactionInterceptor`
|
|
144
|
-
- `DRIZZLE_DATABASE`, `DRIZZLE_DISPOSE`, `DRIZZLE_OPTIONS`
|
|
147
|
+
- `DRIZZLE_DATABASE`, `DRIZZLE_DISPOSE`, `DRIZZLE_HANDLE_PROVIDER`, `DRIZZLE_OPTIONS`
|
|
145
148
|
- `createDrizzlePlatformStatusSnapshot(...)`
|
|
146
149
|
- `DrizzleDatabaseLike`
|
|
147
150
|
- `DrizzleModuleOptions`
|
|
148
151
|
- `DrizzleHandleProvider`
|
|
149
152
|
|
|
153
|
+
`DRIZZLE_HANDLE_PROVIDER` is an alias token for the lifecycle-aware `DrizzleDatabase` wrapper. Health integrations such as `@fluojs/terminus` use this token to read `createPlatformStatusSnapshot()` before falling back to raw database pings.
|
|
154
|
+
|
|
150
155
|
### `DrizzleModule`
|
|
151
156
|
|
|
152
157
|
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
package/dist/database.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class DrizzleDatabase<TDatabase extends DrizzleDatabaseLike<TTran
|
|
|
16
16
|
private readonly databaseOptions;
|
|
17
17
|
private readonly transactions;
|
|
18
18
|
private readonly activeRequestTransactions;
|
|
19
|
+
private activeRequestTransactionStatusCount;
|
|
19
20
|
private lifecycleState;
|
|
20
21
|
constructor(database: TDatabase, dispose?: ((database: TDatabase) => Promise<void> | void) | undefined, databaseOptions?: DrizzleRuntimeOptions);
|
|
21
22
|
/**
|
|
@@ -64,9 +65,13 @@ export declare class DrizzleDatabase<TDatabase extends DrizzleDatabaseLike<TTran
|
|
|
64
65
|
requestTransaction<T>(fn: () => Promise<T>, signal?: AbortSignal, options?: TTransactionOptions): Promise<T>;
|
|
65
66
|
private executeTransaction;
|
|
66
67
|
private executeRequestTransaction;
|
|
68
|
+
private executeNestedRequestTransaction;
|
|
67
69
|
private executeRequestFallback;
|
|
70
|
+
private assertRequestTransactionsAvailable;
|
|
71
|
+
private throwIfRequestAborted;
|
|
68
72
|
private trackActiveRequestTransaction;
|
|
69
73
|
private untrackActiveRequestTransaction;
|
|
74
|
+
private markRequestTransactionInactiveForStatus;
|
|
70
75
|
private resolveTransactionRunner;
|
|
71
76
|
}
|
|
72
77
|
export {};
|
package/dist/database.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAK7D,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAuBpB,KAAK,qBAAqB,GAAG;IAC3B,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AA8CF;;;;;;GAMG;AACH,qBACa,eAAe,CAC1B,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,CAC7B,YAAW,qBAAqB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,qBAAqB;IAQ3G,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe;IARlC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqE;IAClG,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAuC;IACjF,OAAO,CAAC,mCAAmC,CAAK;IAChD,OAAO,CAAC,cAAc,CAAkD;gBAGrD,QAAQ,EAAE,SAAS,EACnB,OAAO,CAAC,GAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,aAAA,EACvD,eAAe,GAAE,qBAAqD;IAGzF;;;;;;;;;OASG;IACH,OAAO,IAAI,SAAS,GAAG,oBAAoB;IAI3C,qGAAqG;IAC/F,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5C,yFAAyF;IACzF,4BAA4B;IAS5B;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAIrF;;;;;;;;;;;;OAYG;IACG,kBAAkB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;YAIpG,kBAAkB;YAmDlB,yBAAyB;YA8BzB,+BAA+B;YA6C/B,sBAAsB;IAkBpC,OAAO,CAAC,kCAAkC;IAM1C,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,6BAA6B;IAOrC,OAAO,CAAC,+BAA+B;IAKvC,OAAO,CAAC,uCAAuC;IAO/C,OAAO,CAAC,wBAAwB;CAWjC"}
|
package/dist/database.js
CHANGED
|
@@ -5,13 +5,46 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
|
|
|
5
5
|
function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
|
|
6
6
|
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
7
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
|
-
import { createRequestAbortContext, raceWithAbort, trackActiveRequestTransaction, untrackActiveRequestTransaction } from '@fluojs/runtime';
|
|
8
|
+
import { createAbortError, createRequestAbortContext, raceWithAbort, trackActiveRequestTransaction, untrackActiveRequestTransaction } from '@fluojs/runtime';
|
|
9
9
|
import { Inject } from '@fluojs/core';
|
|
10
10
|
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS } from './tokens.js';
|
|
11
11
|
import { createDrizzlePlatformStatusSnapshot } from './status.js';
|
|
12
12
|
const TRANSACTION_NOT_SUPPORTED_ERROR = 'Transaction not supported: Drizzle database does not implement transaction.';
|
|
13
13
|
const NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR = 'Nested Drizzle transaction options are not supported because the active transaction context is reused.';
|
|
14
|
-
|
|
14
|
+
const REQUEST_TRANSACTION_UNAVAILABLE_ERROR = 'Drizzle request transactions are not available during shutdown.';
|
|
15
|
+
function createRequestAbortSignalView(parentSignal, signal) {
|
|
16
|
+
if (!signal) {
|
|
17
|
+
return {
|
|
18
|
+
cleanup() {},
|
|
19
|
+
signal: parentSignal
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const forwardParentAbort = () => controller.abort(parentSignal.reason);
|
|
24
|
+
const forwardRequestAbort = () => controller.abort(signal.reason);
|
|
25
|
+
if (parentSignal.aborted) {
|
|
26
|
+
forwardParentAbort();
|
|
27
|
+
} else {
|
|
28
|
+
parentSignal.addEventListener('abort', forwardParentAbort, {
|
|
29
|
+
once: true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (signal.aborted) {
|
|
33
|
+
forwardRequestAbort();
|
|
34
|
+
} else {
|
|
35
|
+
signal.addEventListener('abort', forwardRequestAbort, {
|
|
36
|
+
once: true
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
cleanup() {
|
|
41
|
+
parentSignal.removeEventListener('abort', forwardParentAbort);
|
|
42
|
+
signal.removeEventListener('abort', forwardRequestAbort);
|
|
43
|
+
},
|
|
44
|
+
signal: controller.signal
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
15
48
|
/**
|
|
16
49
|
* Transaction-aware Drizzle wrapper that integrates request scoping and shutdown handling with the Fluo runtime.
|
|
17
50
|
*
|
|
@@ -19,12 +52,14 @@ let _DrizzleDatabase;
|
|
|
19
52
|
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved inside `database.transaction(...)` callbacks.
|
|
20
53
|
* @typeParam TTransactionOptions Options forwarded to the underlying Drizzle transaction runner.
|
|
21
54
|
*/
|
|
55
|
+
let _DrizzleDatabase;
|
|
22
56
|
class DrizzleDatabase {
|
|
23
57
|
static {
|
|
24
58
|
[_DrizzleDatabase, _initClass] = _applyDecs(this, [Inject(DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS)], []).c;
|
|
25
59
|
}
|
|
26
60
|
transactions = new AsyncLocalStorage();
|
|
27
61
|
activeRequestTransactions = new Set();
|
|
62
|
+
activeRequestTransactionStatusCount = 0;
|
|
28
63
|
lifecycleState = 'ready';
|
|
29
64
|
constructor(database, dispose, databaseOptions = {
|
|
30
65
|
strictTransactions: false
|
|
@@ -45,16 +80,17 @@ class DrizzleDatabase {
|
|
|
45
80
|
* @returns The transaction-scoped database inside an active boundary, or the root database outside one.
|
|
46
81
|
*/
|
|
47
82
|
current() {
|
|
48
|
-
return this.transactions.getStore() ?? this.database;
|
|
83
|
+
return this.transactions.getStore()?.database ?? this.database;
|
|
49
84
|
}
|
|
50
85
|
|
|
51
86
|
/** Aborts active request transactions, waits for settlement, then runs the optional dispose hook. */
|
|
52
87
|
async onApplicationShutdown() {
|
|
53
88
|
this.lifecycleState = 'shutting-down';
|
|
54
|
-
|
|
89
|
+
const activeRequestTransactions = Array.from(this.activeRequestTransactions);
|
|
90
|
+
for (const transaction of activeRequestTransactions) {
|
|
55
91
|
transaction.abort(new Error('Application shutdown interrupted an open request transaction.'));
|
|
56
92
|
}
|
|
57
|
-
await Promise.allSettled(
|
|
93
|
+
await Promise.allSettled(activeRequestTransactions.map(transaction => transaction.settled));
|
|
58
94
|
if (this.dispose) {
|
|
59
95
|
await this.dispose(this.database);
|
|
60
96
|
}
|
|
@@ -64,7 +100,7 @@ class DrizzleDatabase {
|
|
|
64
100
|
/** Produces the shared persistence status snapshot for platform diagnostics surfaces. */
|
|
65
101
|
createPlatformStatusSnapshot() {
|
|
66
102
|
return createDrizzlePlatformStatusSnapshot({
|
|
67
|
-
activeRequestTransactions: this.
|
|
103
|
+
activeRequestTransactions: this.activeRequestTransactionStatusCount,
|
|
68
104
|
lifecycleState: this.lifecycleState,
|
|
69
105
|
strictTransactions: this.databaseOptions.strictTransactions,
|
|
70
106
|
supportsTransaction: typeof this.database.transaction === 'function'
|
|
@@ -111,8 +147,8 @@ class DrizzleDatabase {
|
|
|
111
147
|
if (options !== undefined) {
|
|
112
148
|
throw new Error(NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR);
|
|
113
149
|
}
|
|
114
|
-
if (requestScoped
|
|
115
|
-
return
|
|
150
|
+
if (requestScoped) {
|
|
151
|
+
return this.executeNestedRequestTransaction(current, fn, signal);
|
|
116
152
|
}
|
|
117
153
|
return fn();
|
|
118
154
|
}
|
|
@@ -124,36 +160,108 @@ class DrizzleDatabase {
|
|
|
124
160
|
return fn();
|
|
125
161
|
}
|
|
126
162
|
if (!requestScoped) {
|
|
127
|
-
|
|
163
|
+
const deferredRequestTransactionSettlements = new Set();
|
|
164
|
+
try {
|
|
165
|
+
return await transactionRunner(transactionDatabase => this.transactions.run({
|
|
166
|
+
database: transactionDatabase,
|
|
167
|
+
deferredRequestTransactionSettlements
|
|
168
|
+
}, fn), options);
|
|
169
|
+
} finally {
|
|
170
|
+
for (const handle of deferredRequestTransactionSettlements) {
|
|
171
|
+
this.untrackActiveRequestTransaction(handle);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
128
174
|
}
|
|
129
175
|
return this.executeRequestTransaction(transactionRunner, fn, options, signal);
|
|
130
176
|
}
|
|
131
177
|
async executeRequestTransaction(transactionRunner, fn, options, signal) {
|
|
178
|
+
this.assertRequestTransactionsAvailable();
|
|
132
179
|
const abortContext = createRequestAbortContext(signal);
|
|
133
180
|
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
134
181
|
try {
|
|
135
|
-
|
|
182
|
+
const result = await transactionRunner(transactionDatabase => this.transactions.run({
|
|
183
|
+
database: transactionDatabase,
|
|
184
|
+
requestAbortSignal: abortContext.signal
|
|
185
|
+
}, () => raceWithAbort(fn, abortContext.signal)), options);
|
|
186
|
+
this.throwIfRequestAborted(abortContext.signal);
|
|
187
|
+
return result;
|
|
136
188
|
} finally {
|
|
137
189
|
abortContext.cleanup();
|
|
138
190
|
this.untrackActiveRequestTransaction(active);
|
|
139
191
|
}
|
|
140
192
|
}
|
|
193
|
+
async executeNestedRequestTransaction(current, fn, signal) {
|
|
194
|
+
if (current.requestAbortSignal) {
|
|
195
|
+
const abortSignalView = createRequestAbortSignalView(current.requestAbortSignal, signal);
|
|
196
|
+
try {
|
|
197
|
+
const result = await raceWithAbort(fn, abortSignalView.signal);
|
|
198
|
+
this.throwIfRequestAborted(abortSignalView.signal);
|
|
199
|
+
return result;
|
|
200
|
+
} finally {
|
|
201
|
+
abortSignalView.cleanup();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
this.assertRequestTransactionsAvailable();
|
|
205
|
+
const abortContext = createRequestAbortContext(signal);
|
|
206
|
+
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
207
|
+
current.deferredRequestTransactionSettlements?.add(active);
|
|
208
|
+
try {
|
|
209
|
+
const result = await this.transactions.run({
|
|
210
|
+
database: current.database,
|
|
211
|
+
requestAbortSignal: abortContext.signal
|
|
212
|
+
}, () => raceWithAbort(fn, abortContext.signal));
|
|
213
|
+
this.throwIfRequestAborted(abortContext.signal);
|
|
214
|
+
return result;
|
|
215
|
+
} finally {
|
|
216
|
+
abortContext.cleanup();
|
|
217
|
+
if (current.deferredRequestTransactionSettlements) {
|
|
218
|
+
this.markRequestTransactionInactiveForStatus(active);
|
|
219
|
+
} else {
|
|
220
|
+
this.untrackActiveRequestTransaction(active);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
141
224
|
async executeRequestFallback(fn, signal) {
|
|
225
|
+
this.assertRequestTransactionsAvailable();
|
|
142
226
|
const abortContext = createRequestAbortContext(signal);
|
|
143
227
|
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
144
228
|
try {
|
|
145
|
-
|
|
229
|
+
const result = await raceWithAbort(fn, abortContext.signal);
|
|
230
|
+
this.throwIfRequestAborted(abortContext.signal);
|
|
231
|
+
return result;
|
|
146
232
|
} finally {
|
|
147
233
|
abortContext.cleanup();
|
|
148
234
|
this.untrackActiveRequestTransaction(active);
|
|
149
235
|
}
|
|
150
236
|
}
|
|
237
|
+
assertRequestTransactionsAvailable() {
|
|
238
|
+
if (this.lifecycleState !== 'ready') {
|
|
239
|
+
throw new Error(REQUEST_TRANSACTION_UNAVAILABLE_ERROR);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
throwIfRequestAborted(signal) {
|
|
243
|
+
if (signal.aborted) {
|
|
244
|
+
throw createAbortError(signal.reason);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
151
247
|
trackActiveRequestTransaction(controller) {
|
|
152
|
-
|
|
248
|
+
const handle = trackActiveRequestTransaction(this.activeRequestTransactions, controller);
|
|
249
|
+
this.activeRequestTransactionStatusCount += 1;
|
|
250
|
+
return {
|
|
251
|
+
...handle,
|
|
252
|
+
statusActive: true
|
|
253
|
+
};
|
|
153
254
|
}
|
|
154
255
|
untrackActiveRequestTransaction(handle) {
|
|
256
|
+
this.markRequestTransactionInactiveForStatus(handle);
|
|
155
257
|
untrackActiveRequestTransaction(this.activeRequestTransactions, handle);
|
|
156
258
|
}
|
|
259
|
+
markRequestTransactionInactiveForStatus(handle) {
|
|
260
|
+
if (handle.statusActive) {
|
|
261
|
+
this.activeRequestTransactionStatusCount -= 1;
|
|
262
|
+
handle.statusActive = false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
157
265
|
resolveTransactionRunner() {
|
|
158
266
|
if (typeof this.database.transaction !== 'function') {
|
|
159
267
|
if (this.databaseOptions.strictTransactions) {
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAc5E,KAAK,yBAAyB,CAC5B,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,EACpB,mBAAmB,IACjB,kBAAkB,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAChH,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAc5E,KAAK,yBAAyB,CAC5B,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,EACpB,mBAAmB,IACjB,kBAAkB,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAChH,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,CAAC;AAoI7F;;GAEG;AACH,qBAAa,aAAa;IACxB,+DAA+D;IAC/D,MAAM,CAAC,OAAO,CACZ,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,UAAU;IAIlG,uEAAuE;IACvE,MAAM,CAAC,YAAY,CACjB,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,yBAAyB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,UAAU;CAGxG"}
|
package/dist/module.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { defineModule } from '@fluojs/runtime';
|
|
2
2
|
import { DrizzleDatabase } from './database.js';
|
|
3
|
-
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS } from './tokens.js';
|
|
3
|
+
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_HANDLE_PROVIDER, DRIZZLE_OPTIONS } from './tokens.js';
|
|
4
4
|
import { DrizzleTransactionInterceptor } from './transaction.js';
|
|
5
5
|
const DRIZZLE_NORMALIZED_OPTIONS = Symbol('fluo.drizzle.normalized-options');
|
|
6
|
-
const DRIZZLE_MODULE_EXPORTS = [DrizzleDatabase, DrizzleTransactionInterceptor];
|
|
6
|
+
const DRIZZLE_MODULE_EXPORTS = [DrizzleDatabase, DrizzleTransactionInterceptor, DRIZZLE_HANDLE_PROVIDER];
|
|
7
7
|
function normalizeDrizzleModuleOptions(options) {
|
|
8
8
|
return {
|
|
9
9
|
...options,
|
|
@@ -28,7 +28,10 @@ function createDrizzleRuntimeProviders(normalizedOptionsProvider) {
|
|
|
28
28
|
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
29
29
|
provide: DRIZZLE_OPTIONS,
|
|
30
30
|
useFactory: options => createRuntimeOptionsProviderValue(options.strictTransactions)
|
|
31
|
-
}, DrizzleDatabase,
|
|
31
|
+
}, DrizzleDatabase, {
|
|
32
|
+
provide: DRIZZLE_HANDLE_PROVIDER,
|
|
33
|
+
useExisting: DrizzleDatabase
|
|
34
|
+
}, DrizzleTransactionInterceptor];
|
|
32
35
|
}
|
|
33
36
|
function createMemoizedDrizzleOptionsResolver(options) {
|
|
34
37
|
let cachedResult;
|
package/dist/tokens.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Dependency-injection token for the raw Drizzle database handle. */
|
|
2
2
|
export declare const DRIZZLE_DATABASE: unique symbol;
|
|
3
|
+
/** Dependency-injection token for the lifecycle-aware Drizzle database wrapper. */
|
|
4
|
+
export declare const DRIZZLE_HANDLE_PROVIDER: unique symbol;
|
|
3
5
|
/** Dependency-injection token for the optional Drizzle shutdown dispose hook. */
|
|
4
6
|
export declare const DRIZZLE_DISPOSE: unique symbol;
|
|
5
7
|
/** Dependency-injection token for normalized Drizzle runtime options. */
|
package/dist/tokens.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,eAAsC,CAAC;AACpE,iFAAiF;AACjF,eAAO,MAAM,eAAe,eAAqC,CAAC;AAClE,yEAAyE;AACzE,eAAO,MAAM,eAAe,eAAqC,CAAC"}
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,eAAsC,CAAC;AACpE,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,eAA6C,CAAC;AAClF,iFAAiF;AACjF,eAAO,MAAM,eAAe,eAAqC,CAAC;AAClE,yEAAyE;AACzE,eAAO,MAAM,eAAe,eAAqC,CAAC"}
|
package/dist/tokens.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Dependency-injection token for the raw Drizzle database handle. */
|
|
2
2
|
export const DRIZZLE_DATABASE = Symbol.for('fluo.drizzle.database');
|
|
3
|
+
/** Dependency-injection token for the lifecycle-aware Drizzle database wrapper. */
|
|
4
|
+
export const DRIZZLE_HANDLE_PROVIDER = Symbol.for('fluo.drizzle.handle-provider');
|
|
3
5
|
/** Dependency-injection token for the optional Drizzle shutdown dispose hook. */
|
|
4
6
|
export const DRIZZLE_DISPOSE = Symbol.for('fluo.drizzle.dispose');
|
|
5
7
|
/** Dependency-injection token for normalized Drizzle runtime options. */
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"transaction",
|
|
10
10
|
"als"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.0-beta.
|
|
12
|
+
"version": "1.0.0-beta.5",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^1.0.0-beta.
|
|
40
|
-
"@fluojs/http": "^1.0.0-beta.
|
|
41
|
-
"@fluojs/di": "^1.0.0-beta.
|
|
42
|
-
"@fluojs/runtime": "^1.0.0-beta.
|
|
39
|
+
"@fluojs/core": "^1.0.0-beta.6",
|
|
40
|
+
"@fluojs/http": "^1.0.0-beta.11",
|
|
41
|
+
"@fluojs/di": "^1.0.0-beta.8",
|
|
42
|
+
"@fluojs/runtime": "^1.0.0-beta.12"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"drizzle-orm": ">=0.30.0"
|