@nest-omni/core 4.1.3-15 → 4.1.3-18

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.
Files changed (55) hide show
  1. package/audit/audit.module.js +7 -0
  2. package/audit/services/entity-audit.service.js +2 -1
  3. package/audit/services/manual-audit-log.service.js +2 -2
  4. package/audit/services/multi-database.service.d.ts +0 -5
  5. package/audit/services/multi-database.service.js +0 -24
  6. package/audit/services/transaction-audit.service.js +3 -2
  7. package/cache/dependencies/db.dependency.d.ts +2 -7
  8. package/cache/dependencies/db.dependency.js +4 -11
  9. package/http-client/examples/proxy-from-environment.example.d.ts +1 -1
  10. package/http-client/examples/proxy-from-environment.example.js +18 -19
  11. package/http-client/services/logging.service.js +2 -3
  12. package/index.d.ts +1 -1
  13. package/index.js +1 -1
  14. package/package.json +3 -2
  15. package/setup/bootstrap.setup.d.ts +1 -1
  16. package/shared/service-registry.module.js +2 -15
  17. package/shared/services/api-config.service.js +1 -0
  18. package/validators/is-exists.validator.d.ts +2 -7
  19. package/validators/is-exists.validator.js +2 -24
  20. package/validators/is-unique.validator.d.ts +2 -7
  21. package/validators/is-unique.validator.js +2 -24
  22. package/transaction/__tests__/mocks.d.ts +0 -9
  23. package/transaction/__tests__/mocks.js +0 -33
  24. package/transaction/base-service-transaction.d.ts +0 -106
  25. package/transaction/base-service-transaction.js +0 -317
  26. package/transaction/cls-compatibility.service.d.ts +0 -55
  27. package/transaction/cls-compatibility.service.js +0 -127
  28. package/transaction/data-source-registry.d.ts +0 -91
  29. package/transaction/data-source-registry.js +0 -349
  30. package/transaction/data-source.util.d.ts +0 -142
  31. package/transaction/data-source.util.js +0 -330
  32. package/transaction/database-adapter.d.ts +0 -44
  33. package/transaction/database-adapter.js +0 -240
  34. package/transaction/decorators/entity-datasource.decorator.d.ts +0 -62
  35. package/transaction/decorators/entity-datasource.decorator.js +0 -105
  36. package/transaction/index.d.ts +0 -16
  37. package/transaction/index.js +0 -71
  38. package/transaction/logging-transactional.interceptor.d.ts +0 -18
  39. package/transaction/logging-transactional.interceptor.js +0 -163
  40. package/transaction/transaction-context.service.d.ts +0 -137
  41. package/transaction/transaction-context.service.js +0 -411
  42. package/transaction/transaction-manager.d.ts +0 -230
  43. package/transaction/transaction-manager.holder.d.ts +0 -31
  44. package/transaction/transaction-manager.holder.js +0 -42
  45. package/transaction/transaction-manager.js +0 -1001
  46. package/transaction/transaction-synchronization.d.ts +0 -171
  47. package/transaction/transaction-synchronization.js +0 -380
  48. package/transaction/transaction.errors.d.ts +0 -91
  49. package/transaction/transaction.errors.js +0 -206
  50. package/transaction/transaction.module.d.ts +0 -30
  51. package/transaction/transaction.module.js +0 -126
  52. package/transaction/transactional.decorator.d.ts +0 -82
  53. package/transaction/transactional.decorator.js +0 -320
  54. package/transaction/typeorm-module-wrapper.d.ts +0 -96
  55. package/transaction/typeorm-module-wrapper.js +0 -197
@@ -1,1001 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- var __param = (this && this.__param) || function (paramIndex, decorator) {
12
- return function (target, key) { decorator(target, key, paramIndex); }
13
- };
14
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
- return new (P || (P = Promise))(function (resolve, reject) {
17
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
- step((generator = generator.apply(thisArg, _arguments || [])).next());
21
- });
22
- };
23
- var TransactionManager_1;
24
- Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.TransactionManager = exports.TransactionContextManager = exports.IsolationLevel = exports.Propagation = void 0;
26
- const common_1 = require("@nestjs/common");
27
- const transaction_context_service_1 = require("./transaction-context.service");
28
- const entity_datasource_decorator_1 = require("./decorators/entity-datasource.decorator");
29
- const transaction_errors_1 = require("./transaction.errors");
30
- const transaction_synchronization_1 = require("./transaction-synchronization");
31
- const database_adapter_1 = require("./database-adapter");
32
- /**
33
- * 事务传播行为
34
- */
35
- var Propagation;
36
- (function (Propagation) {
37
- /**
38
- * 支持当前事务,如果不存在就创建一个新事务
39
- */
40
- Propagation[Propagation["REQUIRED"] = 0] = "REQUIRED";
41
- /**
42
- * 支持当前事务,如果不存在就以非事务方式执行
43
- */
44
- Propagation[Propagation["SUPPORTS"] = 1] = "SUPPORTS";
45
- /**
46
- * 支持当前事务,如果不存在就抛出异常
47
- */
48
- Propagation[Propagation["MANDATORY"] = 2] = "MANDATORY";
49
- /**
50
- * 创建新事务,如果当前存在事务就挂起它
51
- */
52
- Propagation[Propagation["REQUIRES_NEW"] = 3] = "REQUIRES_NEW";
53
- /**
54
- * 以非事务方式执行,如果当前存在事务就挂起它
55
- */
56
- Propagation[Propagation["NOT_SUPPORTED"] = 4] = "NOT_SUPPORTED";
57
- /**
58
- * 以非事务方式执行,如果当前存在事务就抛出异常
59
- */
60
- Propagation[Propagation["NEVER"] = 5] = "NEVER";
61
- /**
62
- * 如果当前存在事务,就在嵌套事务中执行
63
- */
64
- Propagation[Propagation["NESTED"] = 6] = "NESTED";
65
- })(Propagation || (exports.Propagation = Propagation = {}));
66
- /**
67
- * 事务隔离级别
68
- */
69
- var IsolationLevel;
70
- (function (IsolationLevel) {
71
- IsolationLevel[IsolationLevel["DEFAULT"] = -1] = "DEFAULT";
72
- IsolationLevel[IsolationLevel["READ_UNCOMMITTED"] = 1] = "READ_UNCOMMITTED";
73
- IsolationLevel[IsolationLevel["READ_COMMITTED"] = 2] = "READ_COMMITTED";
74
- IsolationLevel[IsolationLevel["REPEATABLE_READ"] = 3] = "REPEATABLE_READ";
75
- IsolationLevel[IsolationLevel["SERIALIZABLE"] = 4] = "SERIALIZABLE";
76
- })(IsolationLevel || (exports.IsolationLevel = IsolationLevel = {}));
77
- /**
78
- * 统一的事务上下文管理类
79
- * 减少状态管理复杂度,避免不一致
80
- */
81
- let TransactionContextManager = class TransactionContextManager {
82
- constructor() {
83
- this.resources = new Map();
84
- this.activeTransactions = new Map();
85
- this.suspendedTransactions = new Map();
86
- }
87
- // 获取方法
88
- getResource(name) {
89
- return this.resources.get(name);
90
- }
91
- getActiveTransaction(name) {
92
- return this.activeTransactions.get(name) || null;
93
- }
94
- getAllActiveTransactions() {
95
- return new Map(this.activeTransactions);
96
- }
97
- getAllResources() {
98
- return new Map(this.resources);
99
- }
100
- // 设置方法
101
- setResource(name, resource) {
102
- this.resources.set(name, resource);
103
- }
104
- setActiveTransaction(name, status) {
105
- this.activeTransactions.set(name, status);
106
- }
107
- // 删除方法
108
- deleteResource(name) {
109
- return this.resources.delete(name);
110
- }
111
- deleteActiveTransaction(name) {
112
- return this.activeTransactions.delete(name);
113
- }
114
- // 挂起和恢复
115
- suspendTransaction(name) {
116
- const resource = this.resources.get(name);
117
- const status = this.activeTransactions.get(name);
118
- if (resource && status) {
119
- const suspended = {
120
- dataSourceName: name,
121
- resource,
122
- status,
123
- };
124
- // Use Map for O(1) lookup
125
- if (!this.suspendedTransactions.has(name)) {
126
- this.suspendedTransactions.set(name, []);
127
- }
128
- this.suspendedTransactions.get(name).push(suspended);
129
- this.resources.delete(name);
130
- this.activeTransactions.delete(name);
131
- return suspended;
132
- }
133
- return null;
134
- }
135
- resumeSuspendedTransaction(name) {
136
- const stack = this.suspendedTransactions.get(name);
137
- if (stack && stack.length > 0) {
138
- const suspended = stack.pop(); // LIFO order
139
- if (stack.length === 0) {
140
- this.suspendedTransactions.delete(name);
141
- }
142
- this.resources.set(name, suspended.resource);
143
- this.activeTransactions.set(name, suspended.status);
144
- return suspended;
145
- }
146
- return null;
147
- }
148
- // 清理所有状态
149
- clear() {
150
- this.resources.clear();
151
- this.activeTransactions.clear();
152
- this.suspendedTransactions.clear();
153
- }
154
- // 获取统计信息
155
- getStats() {
156
- let totalSuspended = 0;
157
- this.suspendedTransactions.forEach(stack => {
158
- totalSuspended += stack.length;
159
- });
160
- return {
161
- activeTransactions: Array.from(this.activeTransactions.values()).map(tx => ({
162
- dataSource: tx.dataSourceName,
163
- nestingLevel: tx.nestingLevel,
164
- startTime: tx.startTime,
165
- propagation: tx.definition.propagation,
166
- isRollbackOnly: tx.isRollbackOnly,
167
- })),
168
- resources: Array.from(this.resources.entries()).map(([name, resource]) => ({
169
- dataSource: name,
170
- hasTransaction: resource.transactionStarted,
171
- nestingLevel: resource.nestingLevel,
172
- })),
173
- suspendedTransactions: totalSuspended,
174
- };
175
- }
176
- };
177
- exports.TransactionContextManager = TransactionContextManager;
178
- exports.TransactionContextManager = TransactionContextManager = __decorate([
179
- (0, common_1.Injectable)({ scope: common_1.Scope.REQUEST })
180
- ], TransactionContextManager);
181
- /**
182
- * 事务管理器
183
- * 统一管理多数据源事务,支持自动嵌套
184
- */
185
- let TransactionManager = TransactionManager_1 = class TransactionManager {
186
- constructor(transactionContext, contextManager, config) {
187
- this.transactionContext = transactionContext;
188
- this.contextManager = contextManager;
189
- this.config = config;
190
- this.logger = new common_1.Logger(TransactionManager_1.name);
191
- }
192
- /**
193
- * 获取或创建事务
194
- * 处理各种传播行为
195
- */
196
- getTransaction(definition) {
197
- return __awaiter(this, void 0, void 0, function* () {
198
- // Validate input
199
- if (!definition) {
200
- throw transaction_errors_1.TransactionError.invalidState('Transaction definition is required');
201
- }
202
- if (definition.timeout !== undefined && definition.timeout < 0) {
203
- throw transaction_errors_1.TransactionError.invalidState('Transaction timeout must be non-negative');
204
- }
205
- // Set default propagation if not specified
206
- if (definition.propagation === undefined) {
207
- definition.propagation = Propagation.REQUIRED;
208
- }
209
- const dataSourceName = definition.dataSourceName || 'default';
210
- const existingTx = this.contextManager.getActiveTransaction(dataSourceName);
211
- switch (definition.propagation) {
212
- case Propagation.REQUIRED:
213
- return this.handleRequired(definition, existingTx, dataSourceName);
214
- case Propagation.REQUIRES_NEW:
215
- return this.handleRequiresNew(definition, dataSourceName);
216
- case Propagation.NESTED:
217
- return this.handleNested(definition, existingTx, dataSourceName);
218
- case Propagation.SUPPORTS:
219
- return this.handleSupports(definition, existingTx, dataSourceName);
220
- case Propagation.NOT_SUPPORTED:
221
- return this.handleNotSupported(definition, dataSourceName);
222
- case Propagation.MANDATORY:
223
- return this.handleMandatory(definition, existingTx, dataSourceName);
224
- case Propagation.NEVER:
225
- return this.handleNever(definition, existingTx, dataSourceName);
226
- default:
227
- throw transaction_errors_1.TransactionError.unsupportedPropagation(definition.propagation);
228
- }
229
- });
230
- }
231
- /**
232
- * 提交事务
233
- */
234
- commit(status) {
235
- return __awaiter(this, void 0, void 0, function* () {
236
- var _a, _b, _c, _d;
237
- if (status.isCompleted) {
238
- return;
239
- }
240
- if (status.isRollbackOnly) {
241
- yield this.rollback(status);
242
- return;
243
- }
244
- const resource = this.contextManager.getResource(status.dataSourceName);
245
- let actualCompletionStatus = transaction_synchronization_1.TransactionSynchronizationStatus.STATUS_COMMITTED;
246
- try {
247
- // 触发 beforeCommit 回调
248
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
249
- yield transaction_synchronization_1.TransactionSynchronizationManager.triggerBeforeCommit(status.definition.readOnly || false, status.dataSourceName);
250
- }
251
- // 触发 beforeCompletion 回调
252
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
253
- yield transaction_synchronization_1.TransactionSynchronizationManager.triggerBeforeCompletion(status.dataSourceName);
254
- }
255
- if (status.isNewTransaction && (resource === null || resource === void 0 ? void 0 : resource.transactionStarted)) {
256
- try {
257
- yield resource.queryRunner.commitTransaction();
258
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
259
- this.logger.log(`Committed transaction on ${status.dataSourceName}`);
260
- }
261
- }
262
- catch (commitError) {
263
- this.logger.error(`Failed to commit transaction on ${status.dataSourceName}`, commitError);
264
- throw commitError;
265
- }
266
- }
267
- else if (status.nestingLevel > 1 && (resource === null || resource === void 0 ? void 0 : resource.transactionStarted) && resource.savepoints.length > 0) {
268
- // 嵌套事务提交:释放最近的保存点
269
- const savepointName = resource.savepoints.pop();
270
- try {
271
- yield database_adapter_1.DatabaseAdapter.releaseSavepoint(resource.queryRunner, savepointName);
272
- if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.logTransactionDetails) {
273
- this.logger.log(`Released savepoint ${savepointName} on ${status.dataSourceName}`);
274
- }
275
- }
276
- catch (releaseError) {
277
- this.logger.error(`Failed to release savepoint ${savepointName}`, releaseError);
278
- throw releaseError;
279
- }
280
- }
281
- this.markCompleted(status);
282
- this.contextManager.deleteActiveTransaction(status.dataSourceName);
283
- // 触发 afterCommit 回调
284
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
285
- yield transaction_synchronization_1.TransactionSynchronizationManager.triggerAfterCommit(status.dataSourceName);
286
- }
287
- // 清理超时定时器
288
- this.clearTimeout(status);
289
- }
290
- catch (error) {
291
- actualCompletionStatus = transaction_synchronization_1.TransactionSynchronizationStatus.STATUS_ROLLED_BACK;
292
- yield this.rollbackOnCommitException(status, error);
293
- throw error;
294
- }
295
- finally {
296
- // 触发 afterCompletion 回调 - 使用实际完成状态
297
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
298
- yield transaction_synchronization_1.TransactionSynchronizationManager.triggerAfterCompletion(actualCompletionStatus, status.dataSourceName);
299
- // 清理同步状态
300
- if (status.isNewTransaction) {
301
- transaction_synchronization_1.TransactionSynchronizationManager.clearSynchronization(status.dataSourceName);
302
- }
303
- }
304
- // 只有新事务才需要释放 QueryRunner
305
- // 嵌套事务(NESTED)使用保存点,不应该释放 QueryRunner
306
- // 注意: 非事务连接(transactionStarted=false)也需要释放QueryRunner
307
- if ((resource === null || resource === void 0 ? void 0 : resource.queryRunner) && status.isNewTransaction) {
308
- try {
309
- yield resource.queryRunner.release();
310
- if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.logTransactionDetails) {
311
- this.logger.log(`Released QueryRunner for ${status.dataSourceName}`);
312
- }
313
- }
314
- catch (releaseError) {
315
- this.logger.error(`Failed to release QueryRunner for ${status.dataSourceName}`, releaseError);
316
- // 不抛出错误,避免覆盖原始错误
317
- }
318
- }
319
- // 最后恢复挂起的事务 - 在所有清理完成后
320
- if (status.isNewTransaction) {
321
- const suspended = this.contextManager.resumeSuspendedTransaction(status.dataSourceName);
322
- if (suspended && ((_d = this.config) === null || _d === void 0 ? void 0 : _d.logTransactionDetails)) {
323
- this.logger.log(`Resumed suspended transaction on ${status.dataSourceName}`);
324
- }
325
- }
326
- }
327
- });
328
- }
329
- /**
330
- * 回滚事务
331
- */
332
- rollback(status) {
333
- return __awaiter(this, void 0, void 0, function* () {
334
- var _a, _b, _c, _d;
335
- if (status.isCompleted) {
336
- return;
337
- }
338
- const resource = this.contextManager.getResource(status.dataSourceName);
339
- try {
340
- // 触发 beforeCompletion 回调
341
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
342
- yield transaction_synchronization_1.TransactionSynchronizationManager.triggerBeforeCompletion(status.dataSourceName);
343
- }
344
- if (status.nestingLevel > 1 && (resource === null || resource === void 0 ? void 0 : resource.transactionStarted) && resource.savepoints.length > 0) {
345
- // 嵌套事务:回滚到最近的保存点
346
- const savepointName = resource.savepoints.pop();
347
- try {
348
- yield database_adapter_1.DatabaseAdapter.rollbackToSavepoint(resource.queryRunner, savepointName);
349
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
350
- this.logger.log(`Rolled back to savepoint ${savepointName} on ${status.dataSourceName}`);
351
- }
352
- }
353
- catch (rollbackError) {
354
- this.logger.error(`Failed to rollback to savepoint ${savepointName}`, rollbackError);
355
- throw rollbackError;
356
- }
357
- }
358
- else if (resource === null || resource === void 0 ? void 0 : resource.transactionStarted) {
359
- // 根事务或无保存点:完全回滚
360
- try {
361
- yield resource.queryRunner.rollbackTransaction();
362
- }
363
- catch (rollbackError) {
364
- this.logger.error(`Failed to rollback transaction on ${status.dataSourceName}`, rollbackError);
365
- throw rollbackError;
366
- }
367
- if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.logTransactionDetails) {
368
- this.logger.log(`Rolled back transaction on ${status.dataSourceName}`);
369
- }
370
- }
371
- this.markCompleted(status);
372
- this.contextManager.deleteActiveTransaction(status.dataSourceName);
373
- // 清理超时定时器
374
- this.clearTimeout(status);
375
- }
376
- finally {
377
- // 触发 afterCompletion 回调
378
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
379
- yield transaction_synchronization_1.TransactionSynchronizationManager.triggerAfterCompletion(transaction_synchronization_1.TransactionSynchronizationStatus.STATUS_ROLLED_BACK, status.dataSourceName);
380
- // 清理同步状态
381
- if (status.isNewTransaction) {
382
- transaction_synchronization_1.TransactionSynchronizationManager.clearSynchronization(status.dataSourceName);
383
- }
384
- }
385
- // Ensure QueryRunner is always released regardless of transaction state
386
- if (resource === null || resource === void 0 ? void 0 : resource.queryRunner) {
387
- try {
388
- yield resource.queryRunner.release();
389
- if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.logTransactionDetails) {
390
- this.logger.log(`Released QueryRunner for ${status.dataSourceName}`);
391
- }
392
- }
393
- catch (releaseError) {
394
- this.logger.error(`Failed to release QueryRunner for ${status.dataSourceName}`, releaseError);
395
- // Don't throw error to avoid masking the original error
396
- }
397
- }
398
- // Clean up resource
399
- this.contextManager.deleteResource(status.dataSourceName);
400
- // 最后恢复挂起的事务 - 在所有清理完成后
401
- if (status.isNewTransaction) {
402
- const suspended = this.contextManager.resumeSuspendedTransaction(status.dataSourceName);
403
- if (suspended && ((_d = this.config) === null || _d === void 0 ? void 0 : _d.logTransactionDetails)) {
404
- this.logger.log(`Resumed suspended transaction on ${status.dataSourceName}`);
405
- }
406
- }
407
- }
408
- });
409
- }
410
- /**
411
- * 获取当前事务的 EntityManager
412
- */
413
- getCurrentEntityManager(dataSourceName = 'default') {
414
- const resource = this.contextManager.getResource(dataSourceName);
415
- if (resource === null || resource === void 0 ? void 0 : resource.transactionStarted) {
416
- return resource.queryRunner.manager;
417
- }
418
- // 如果没有活跃事务,尝试从事务上下文获取
419
- return this.transactionContext.getEntityManager(dataSourceName);
420
- }
421
- /**
422
- * 获取当前事务状态
423
- */
424
- getCurrentTransaction(dataSourceName = 'default') {
425
- return this.contextManager.getActiveTransaction(dataSourceName);
426
- }
427
- /**
428
- * 获取事务统计
429
- */
430
- getTransactionStats() {
431
- return this.contextManager.getStats();
432
- }
433
- /**
434
- * 根据 Entity 获取数据源名称
435
- * 支持装饰器、静态方法和动态方法
436
- */
437
- getDataSourceForEntity(entityClassOrInstance) {
438
- // 1. 尝试从装饰器获取
439
- const decoratorDataSource = (0, entity_datasource_decorator_1.getEntityDataSource)(entityClassOrInstance);
440
- if (decoratorDataSource) {
441
- return decoratorDataSource;
442
- }
443
- // 2. 检查是否使用动态数据源
444
- if ((0, entity_datasource_decorator_1.isDynamicDataSourceEntity)(entityClassOrInstance)) {
445
- const entity = entityClassOrInstance;
446
- // 如果有 useDataSource 静态方法,调用它
447
- if (typeof entity.useDataSource === 'function') {
448
- return entity.useDataSource();
449
- }
450
- // 如果有实例方法,调用它
451
- if (entity.getDataSource && typeof entity.getDataSource === 'function') {
452
- return entity.getDataSource();
453
- }
454
- }
455
- // 3. 检查基类(如果有继承关系)
456
- let prototype = entityClassOrInstance;
457
- while (prototype && prototype !== Object.prototype) {
458
- const parentDataSource = (0, entity_datasource_decorator_1.getEntityDataSource)(prototype.constructor || prototype);
459
- if (parentDataSource) {
460
- return parentDataSource;
461
- }
462
- prototype = Object.getPrototypeOf(prototype);
463
- }
464
- return null;
465
- }
466
- /**
467
- * 为 Entity 获取或创建 EntityManager
468
- * 自动检测 Entity 的数据源
469
- */
470
- getEntityManagerForEntity(entityClassOrInstance, fallbackDataSourceName = 'default') {
471
- // 优先使用 Entity 指定的数据源
472
- const entityDataSource = this.getDataSourceForEntity(entityClassOrInstance);
473
- const dataSourceName = entityDataSource || fallbackDataSourceName;
474
- return this.getCurrentEntityManager(dataSourceName);
475
- }
476
- // ===== 私有方法 =====
477
- handleRequired(definition, existingTx, dataSourceName) {
478
- if (existingTx && !existingTx.isCompleted) {
479
- // 加入现有事务
480
- return Promise.resolve(this.createParticipatingTransaction(definition, existingTx.nestingLevel + 1, dataSourceName));
481
- }
482
- else {
483
- // 创建新事务
484
- return this.createNewTransaction(definition, 1, dataSourceName);
485
- }
486
- }
487
- handleRequiresNew(definition, dataSourceName) {
488
- return __awaiter(this, void 0, void 0, function* () {
489
- var _a;
490
- // 挂起当前事务(如果存在)
491
- const existingResource = this.contextManager.getResource(dataSourceName);
492
- const existingStatus = this.contextManager.getActiveTransaction(dataSourceName);
493
- if (existingResource && existingStatus) {
494
- // 挂起当前事务
495
- const suspended = this.contextManager.suspendTransaction(dataSourceName);
496
- if (suspended) {
497
- this.transactionContext.clearContextForDataSource(dataSourceName);
498
- }
499
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
500
- this.logger.log(`Suspended transaction on ${dataSourceName} for REQUIRES_NEW`);
501
- }
502
- }
503
- // 创建新事务
504
- return this.createNewTransaction(definition, 1, dataSourceName);
505
- });
506
- }
507
- handleNested(definition, existingTx, dataSourceName) {
508
- return __awaiter(this, void 0, void 0, function* () {
509
- var _a, _b;
510
- if (existingTx && !existingTx.isCompleted) {
511
- // 创建真正的嵌套事务,使用 SAVEPOINT
512
- const resource = this.contextManager.getResource(dataSourceName);
513
- if (!resource || !resource.transactionStarted) {
514
- throw transaction_errors_1.TransactionError.invalidState('No active transaction found for NESTED propagation', dataSourceName);
515
- }
516
- // 创建保存点
517
- const savepointName = `sp_${dataSourceName}_L${existingTx.nestingLevel + 1}_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
518
- let savepointCreated = false;
519
- try {
520
- // 创建保存点
521
- yield database_adapter_1.DatabaseAdapter.createSavepoint(resource.queryRunner, savepointName);
522
- savepointCreated = true;
523
- // 只有创建成功后才更新状态
524
- resource.savepoints.push(savepointName);
525
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
526
- this.logger.log(`Created savepoint ${savepointName} for nested transaction on ${dataSourceName}`);
527
- }
528
- // 创建参与性事务状态
529
- return this.createParticipatingTransaction(definition, existingTx.nestingLevel + 1, dataSourceName);
530
- }
531
- catch (error) {
532
- // 如果保存点已创建但后续失败,需要清理
533
- if (savepointCreated) {
534
- // 从 savepoints 数组中移除(如果已添加)
535
- const lastSavepoint = resource.savepoints[resource.savepoints.length - 1];
536
- if (lastSavepoint === savepointName) {
537
- resource.savepoints.pop();
538
- }
539
- // 尝试回滚 Savepoint(如果数据库已创建)
540
- try {
541
- yield database_adapter_1.DatabaseAdapter.rollbackToSavepoint(resource.queryRunner, savepointName);
542
- if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.logTransactionDetails) {
543
- this.logger.log(`Rolled back savepoint ${savepointName} during cleanup`);
544
- }
545
- }
546
- catch (rollbackError) {
547
- this.logger.error(`Failed to rollback savepoint ${savepointName} during cleanup: ${rollbackError.message}`, rollbackError.stack);
548
- }
549
- }
550
- throw transaction_errors_1.TransactionError.nestedTransactionFailed(`Failed to create nested transaction with savepoint ${savepointName}: ${error.message}`, dataSourceName, error);
551
- }
552
- }
553
- else {
554
- // 没有外部事务,创建新事务
555
- return this.createNewTransaction(definition, 1, dataSourceName);
556
- }
557
- });
558
- }
559
- handleSupports(definition, existingTx, dataSourceName) {
560
- return __awaiter(this, void 0, void 0, function* () {
561
- var _a;
562
- if (existingTx && !existingTx.isCompleted) {
563
- // 有事务,参与现有事务
564
- return this.createParticipatingTransaction(definition, existingTx.nestingLevel + 1, dataSourceName);
565
- }
566
- else {
567
- // 没有事务,创建非事务连接
568
- const dataSource = yield this.getDataSource(dataSourceName);
569
- const queryRunner = dataSource.createQueryRunner();
570
- yield queryRunner.connect();
571
- // 不启动事务
572
- const resource = {
573
- dataSourceName,
574
- dataSource,
575
- queryRunner,
576
- transactionStarted: false,
577
- nestingLevel: 1,
578
- savepoints: [],
579
- };
580
- this.contextManager.setResource(dataSourceName, resource);
581
- this.transactionContext.setContext(dataSourceName, queryRunner.manager);
582
- const status = {
583
- isCompleted: false,
584
- isRollbackOnly: false,
585
- isNewTransaction: true, // 需要清理资源
586
- dataSourceName,
587
- startTime: new Date(),
588
- definition,
589
- nestingLevel: 1,
590
- };
591
- this.contextManager.setActiveTransaction(dataSourceName, status);
592
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
593
- this.logger.log(`Created non-transactional connection for SUPPORTS on ${dataSourceName}`);
594
- }
595
- return status;
596
- }
597
- });
598
- }
599
- handleNotSupported(definition, dataSourceName) {
600
- return __awaiter(this, void 0, void 0, function* () {
601
- var _a, _b;
602
- // 挂起当前事务(如果存在)
603
- const existingResource = this.contextManager.getResource(dataSourceName);
604
- const existingStatus = this.contextManager.getActiveTransaction(dataSourceName);
605
- if (existingResource && existingStatus) {
606
- // 挂起当前事务
607
- const suspended = this.contextManager.suspendTransaction(dataSourceName);
608
- if (suspended) {
609
- this.transactionContext.clearContextForDataSource(dataSourceName);
610
- }
611
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
612
- this.logger.log(`Suspended transaction on ${dataSourceName} for NOT_SUPPORTED`);
613
- }
614
- }
615
- // 创建非事务的数据库连接
616
- const dataSource = yield this.getDataSource(dataSourceName);
617
- const queryRunner = dataSource.createQueryRunner();
618
- yield queryRunner.connect();
619
- // 注意: 不调用 startTransaction(),以非事务方式执行
620
- const resource = {
621
- dataSourceName,
622
- dataSource,
623
- queryRunner,
624
- transactionStarted: false, // 标记为非事务
625
- nestingLevel: 1,
626
- savepoints: [],
627
- };
628
- this.contextManager.setResource(dataSourceName, resource);
629
- this.transactionContext.setContext(dataSourceName, queryRunner.manager);
630
- const status = {
631
- isCompleted: false,
632
- isRollbackOnly: false,
633
- isNewTransaction: true, // 需要清理资源
634
- dataSourceName,
635
- startTime: new Date(),
636
- definition,
637
- nestingLevel: 1,
638
- };
639
- this.contextManager.setActiveTransaction(dataSourceName, status);
640
- if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.logTransactionDetails) {
641
- this.logger.log(`Created non-transactional connection for ${dataSourceName}`);
642
- }
643
- return status;
644
- });
645
- }
646
- handleMandatory(definition, existingTx, dataSourceName) {
647
- if (!existingTx || existingTx.isCompleted) {
648
- throw transaction_errors_1.TransactionError.invalidState('No existing transaction found for MANDATORY propagation', dataSourceName);
649
- }
650
- return this.createParticipatingTransaction(definition, existingTx.nestingLevel + 1, dataSourceName);
651
- }
652
- handleNever(definition, existingTx, dataSourceName) {
653
- return __awaiter(this, void 0, void 0, function* () {
654
- var _a;
655
- if (existingTx && !existingTx.isCompleted) {
656
- throw transaction_errors_1.TransactionError.invalidState('Existing transaction found for NEVER propagation', dataSourceName);
657
- }
658
- // 创建非事务的数据库连接
659
- const dataSource = yield this.getDataSource(dataSourceName);
660
- const queryRunner = dataSource.createQueryRunner();
661
- yield queryRunner.connect();
662
- // 注意: 不调用 startTransaction(),以非事务方式执行
663
- const resource = {
664
- dataSourceName,
665
- dataSource,
666
- queryRunner,
667
- transactionStarted: false, // 标记为非事务
668
- nestingLevel: 1,
669
- savepoints: [],
670
- };
671
- this.contextManager.setResource(dataSourceName, resource);
672
- this.transactionContext.setContext(dataSourceName, queryRunner.manager);
673
- const status = {
674
- isCompleted: false,
675
- isRollbackOnly: false,
676
- isNewTransaction: true, // 需要清理资源
677
- dataSourceName,
678
- startTime: new Date(),
679
- definition,
680
- nestingLevel: 1,
681
- };
682
- this.contextManager.setActiveTransaction(dataSourceName, status);
683
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
684
- this.logger.log(`Created non-transactional connection for NEVER propagation on ${dataSourceName}`);
685
- }
686
- return status;
687
- });
688
- }
689
- createNewTransaction(definition, nestingLevel, dataSourceName) {
690
- return __awaiter(this, void 0, void 0, function* () {
691
- var _a, _b;
692
- let queryRunner = null;
693
- let status = null;
694
- let transactionStarted = false;
695
- try {
696
- const dataSource = yield this.getDataSource(dataSourceName);
697
- queryRunner = dataSource.createQueryRunner();
698
- yield queryRunner.connect();
699
- yield queryRunner.startTransaction(this.convertIsolationLevel(definition.isolationLevel));
700
- transactionStarted = true;
701
- const resource = {
702
- dataSourceName,
703
- dataSource,
704
- queryRunner,
705
- transactionStarted: true,
706
- nestingLevel,
707
- savepoints: [],
708
- };
709
- this.contextManager.setResource(dataSourceName, resource);
710
- this.transactionContext.setContext(dataSourceName, queryRunner.manager);
711
- // 初始化事务同步
712
- if (!transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(dataSourceName)) {
713
- transaction_synchronization_1.TransactionSynchronizationManager.initSynchronization(dataSourceName);
714
- }
715
- // 设置事务信息到同步管理器
716
- transaction_synchronization_1.TransactionSynchronizationManager.setActualTransactionActive(true, dataSourceName);
717
- transaction_synchronization_1.TransactionSynchronizationManager.setCurrentTransactionName(definition.name || null, dataSourceName);
718
- transaction_synchronization_1.TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.readOnly || false, dataSourceName);
719
- if (definition.isolationLevel !== undefined) {
720
- transaction_synchronization_1.TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.isolationLevel, dataSourceName);
721
- }
722
- status = {
723
- isCompleted: false,
724
- isRollbackOnly: false,
725
- isNewTransaction: true,
726
- dataSourceName,
727
- startTime: new Date(),
728
- definition,
729
- nestingLevel,
730
- };
731
- // 设置事务超时
732
- const timeoutMs = this.getTimeoutMs(definition);
733
- if (timeoutMs > 0) {
734
- status.timeoutTimer = setTimeout(() => {
735
- this.handleTransactionTimeout(status);
736
- }, timeoutMs);
737
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
738
- this.logger.log(`Set transaction timeout ${timeoutMs}ms for ${dataSourceName}`);
739
- }
740
- }
741
- this.contextManager.setActiveTransaction(dataSourceName, status);
742
- if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.logTransactionDetails) {
743
- this.logger.log(`Started new transaction on ${dataSourceName} (level: ${nestingLevel})`);
744
- }
745
- return status;
746
- }
747
- catch (error) {
748
- // 增强的错误清理逻辑
749
- this.logger.error(`Failed to create transaction on ${dataSourceName}: ${error.message}`, error.stack);
750
- // Clean up timer if setup fails
751
- if (status === null || status === void 0 ? void 0 : status.timeoutTimer) {
752
- clearTimeout(status.timeoutTimer);
753
- status.timeoutTimer = undefined;
754
- }
755
- // Clean up transaction if started
756
- if (queryRunner && transactionStarted) {
757
- try {
758
- if (queryRunner.isTransactionActive) {
759
- yield queryRunner.rollbackTransaction();
760
- }
761
- }
762
- catch (rollbackError) {
763
- this.logger.error(`Failed to rollback during setup cleanup: ${rollbackError.message}`);
764
- }
765
- }
766
- // Clean up QueryRunner
767
- if (queryRunner) {
768
- try {
769
- yield queryRunner.release();
770
- }
771
- catch (releaseError) {
772
- this.logger.error(`Failed to release QueryRunner during setup error cleanup: ${releaseError.message}`);
773
- }
774
- }
775
- // Clean up context and synchronization
776
- this.contextManager.deleteResource(dataSourceName);
777
- this.contextManager.deleteActiveTransaction(dataSourceName);
778
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(dataSourceName)) {
779
- transaction_synchronization_1.TransactionSynchronizationManager.clearSynchronization(dataSourceName);
780
- }
781
- throw transaction_errors_1.TransactionError.beginFailed(`Failed to create transaction: ${error.message}`, dataSourceName, error);
782
- }
783
- });
784
- }
785
- createParticipatingTransaction(definition, nestingLevel, dataSourceName) {
786
- // 验证必须有现有资源
787
- const resource = this.contextManager.getResource(dataSourceName);
788
- if (!resource) {
789
- throw transaction_errors_1.TransactionError.invalidState('Cannot create participating transaction without existing resource', dataSourceName);
790
- }
791
- const status = {
792
- isCompleted: false,
793
- isRollbackOnly: false,
794
- isNewTransaction: false,
795
- dataSourceName,
796
- startTime: new Date(),
797
- definition,
798
- nestingLevel,
799
- };
800
- // 验证 activeTransaction 状态
801
- const existingTx = this.contextManager.getActiveTransaction(dataSourceName);
802
- if (!existingTx) {
803
- // 如果没有 activeTransaction 但有 resource,说明状态不一致
804
- this.logger.warn(`Creating participating transaction but no active transaction found for ${dataSourceName}. ` +
805
- `This may indicate a state inconsistency.`);
806
- this.contextManager.setActiveTransaction(dataSourceName, status);
807
- }
808
- return status;
809
- }
810
- getActiveTransaction(dataSourceName) {
811
- return this.contextManager.getActiveTransaction(dataSourceName);
812
- }
813
- getDataSource(dataSourceName) {
814
- return __awaiter(this, void 0, void 0, function* () {
815
- return transaction_errors_1.TransactionErrorHandler.safeExecute(() => __awaiter(this, void 0, void 0, function* () {
816
- const dataSource = this.transactionContext.getDataSource(dataSourceName);
817
- if (!dataSource) {
818
- throw transaction_errors_1.TransactionError.dataSourceNotFound(dataSourceName);
819
- }
820
- return dataSource;
821
- }), (error) => transaction_errors_1.TransactionError.beginFailed(`Failed to get data source: ${error.message}`, dataSourceName, error), 'getDataSource');
822
- });
823
- }
824
- convertIsolationLevel(level) {
825
- if (!level || level === IsolationLevel.DEFAULT) {
826
- return undefined;
827
- }
828
- const mapping = {
829
- [IsolationLevel.READ_UNCOMMITTED]: 'READ UNCOMMITTED',
830
- [IsolationLevel.READ_COMMITTED]: 'READ COMMITTED',
831
- [IsolationLevel.REPEATABLE_READ]: 'REPEATABLE READ',
832
- [IsolationLevel.SERIALIZABLE]: 'SERIALIZABLE',
833
- };
834
- return mapping[level];
835
- }
836
- markCompleted(status) {
837
- status.isCompleted = true;
838
- }
839
- removeActiveTransaction(dataSourceName) {
840
- this.contextManager.deleteActiveTransaction(dataSourceName);
841
- }
842
- markParentForRollback(dataSourceName, currentLevel) {
843
- const activeTx = this.contextManager.getActiveTransaction(dataSourceName);
844
- if (activeTx && activeTx.nestingLevel < currentLevel) {
845
- activeTx.isRollbackOnly = true;
846
- }
847
- }
848
- rollbackOnCommitException(status, error) {
849
- return __awaiter(this, void 0, void 0, function* () {
850
- try {
851
- yield this.rollback(status);
852
- }
853
- catch (rollbackError) {
854
- this.logger.error('Rollback after commit exception failed:', rollbackError);
855
- }
856
- });
857
- }
858
- cleanupResource(dataSourceName) {
859
- // 清理事务上下文
860
- this.transactionContext.clearContextForDataSource(dataSourceName);
861
- this.contextManager.deleteResource(dataSourceName);
862
- }
863
- /**
864
- * 恢复挂起的事务 - 已移到 TransactionContextManager 中
865
- * 此方法保留以兼容
866
- */
867
- resumeSuspendedTransaction(dataSourceName) {
868
- return __awaiter(this, void 0, void 0, function* () {
869
- var _a;
870
- const suspended = this.contextManager.resumeSuspendedTransaction(dataSourceName);
871
- if (suspended) {
872
- try {
873
- this.transactionContext.setContext(dataSourceName, suspended.resource.queryRunner.manager);
874
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
875
- this.logger.log(`Resumed suspended transaction on ${dataSourceName}`);
876
- }
877
- }
878
- catch (error) {
879
- throw transaction_errors_1.TransactionError.rollbackFailed(`Failed to resume suspended transaction: ${error.message}`, dataSourceName, suspended.status.definition.name, error);
880
- }
881
- }
882
- });
883
- }
884
- /**
885
- * 获取事务超时时间(毫秒)
886
- */
887
- getTimeoutMs(definition) {
888
- var _a;
889
- // 优先使用定义中的超时时间
890
- if (definition.timeout !== undefined) {
891
- return definition.timeout * 1000; // 转换为毫秒
892
- }
893
- // 使用配置中的默认超时时间
894
- if (((_a = this.config) === null || _a === void 0 ? void 0 : _a.defaultTimeout) !== undefined) {
895
- return this.config.defaultTimeout * 1000;
896
- }
897
- return 0; // 不设置超时
898
- }
899
- /**
900
- * 处理事务超时
901
- */
902
- handleTransactionTimeout(status) {
903
- return __awaiter(this, void 0, void 0, function* () {
904
- var _a;
905
- // 原子性检查并设置状态
906
- if (status.isCompleted) {
907
- return; // 事务已完成,无需处理
908
- }
909
- const timeoutMs = this.getTimeoutMs(status.definition);
910
- const timeoutError = transaction_errors_1.TransactionErrorHandler.handleTimeout(timeoutMs, status.dataSourceName, status.definition.name);
911
- this.logger.error(transaction_errors_1.TransactionErrorHandler.formatMessage(timeoutError));
912
- // 如果有自定义超时回调,在独立的 try-catch 中执行
913
- if (status.definition.onTimeout) {
914
- try {
915
- // 限制回调不能修改事务状态
916
- yield status.definition.onTimeout(status);
917
- this.logger.log(`Custom timeout handler executed for transaction on ${status.dataSourceName}`);
918
- }
919
- catch (callbackError) {
920
- this.logger.error(`Custom timeout handler failed:`, callbackError);
921
- }
922
- }
923
- // 标记为仅回滚
924
- status.isRollbackOnly = true;
925
- let rollbackSuccessful = false;
926
- // 默认处理:回滚事务
927
- // 使用 try-catch 确保即使回滚失败也会清理资源
928
- try {
929
- const resource = this.contextManager.getResource(status.dataSourceName);
930
- if ((resource === null || resource === void 0 ? void 0 : resource.queryRunner) && resource.transactionStarted) {
931
- if (resource.queryRunner.isTransactionActive) {
932
- yield resource.queryRunner.rollbackTransaction();
933
- rollbackSuccessful = true;
934
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
935
- this.logger.log(`Rolled back timed out transaction on ${status.dataSourceName}`);
936
- }
937
- }
938
- yield resource.queryRunner.release();
939
- }
940
- else {
941
- // 资源不可用,视为回滚成功(无需回滚)
942
- rollbackSuccessful = true;
943
- }
944
- }
945
- catch (rollbackError) {
946
- this.logger.error(`Failed to rollback timed out transaction on ${status.dataSourceName}. ` +
947
- `Transaction may be left in inconsistent state. Manual intervention may be required.`, rollbackError);
948
- // 回滚失败,尝试强制释放资源
949
- try {
950
- const resource = this.contextManager.getResource(status.dataSourceName);
951
- if (resource === null || resource === void 0 ? void 0 : resource.queryRunner) {
952
- yield resource.queryRunner.release();
953
- this.logger.warn(`Forcefully released QueryRunner after rollback failure on ${status.dataSourceName}`);
954
- }
955
- }
956
- catch (releaseError) {
957
- this.logger.error(`Failed to release QueryRunner after rollback failure:`, releaseError);
958
- }
959
- }
960
- finally {
961
- // 只有在回滚成功或资源已清理后才标记为完成
962
- if (rollbackSuccessful) {
963
- this.markCompleted(status);
964
- }
965
- // 确保资源被清理
966
- try {
967
- this.contextManager.deleteResource(status.dataSourceName);
968
- this.contextManager.deleteActiveTransaction(status.dataSourceName);
969
- if (transaction_synchronization_1.TransactionSynchronizationManager.isSynchronizationActive(status.dataSourceName)) {
970
- transaction_synchronization_1.TransactionSynchronizationManager.clearSynchronization(status.dataSourceName);
971
- }
972
- }
973
- catch (cleanupError) {
974
- this.logger.error(`Failed to cleanup timed out transaction:`, cleanupError);
975
- }
976
- }
977
- });
978
- }
979
- /**
980
- * 清理事务定时器
981
- * 确保定时器被正确清理,避免内存泄漏
982
- */
983
- clearTimeout(status) {
984
- var _a;
985
- if (status.timeoutTimer) {
986
- clearTimeout(status.timeoutTimer);
987
- status.timeoutTimer = undefined;
988
- if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.logTransactionDetails) {
989
- this.logger.log(`Cleared timeout timer for ${status.dataSourceName}`);
990
- }
991
- }
992
- }
993
- };
994
- exports.TransactionManager = TransactionManager;
995
- exports.TransactionManager = TransactionManager = TransactionManager_1 = __decorate([
996
- (0, common_1.Injectable)({ scope: common_1.Scope.REQUEST }),
997
- __param(2, (0, common_1.Optional)()),
998
- __param(2, (0, common_1.Inject)('TRANSACTION_CONFIG')),
999
- __metadata("design:paramtypes", [transaction_context_service_1.TransactionContextService,
1000
- TransactionContextManager, Object])
1001
- ], TransactionManager);