UNPKG

4.74 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const prom_client_1 = require("prom-client");
4const TransactionManager_1 = require("../transaction/TransactionManager");
5const LogManager_1 = require("../log/LogManager");
6const LOGGER = LogManager_1.LogManager.getLogger(__filename);
7const transactionExecutionDurationsHistogram = new prom_client_1.Histogram({
8 name: 'db_transaction_execute_time',
9 help: 'Time required to execute a transaction',
10 labelNames: ['clientName', 'readonly'],
11 buckets: [0.003, 0.005, 0.01, 0.05, 0.1, 0.3, 1, 5],
12});
13const rolledBackTransactionsCounter = new prom_client_1.Counter({
14 name: 'db_transaction_rollback_counter',
15 help: 'Number of times transactions have been rolled back',
16 labelNames: ['clientName', 'readonly'],
17});
18class DBTransaction {
19 /**
20 *
21 * @param transaction
22 */
23 constructor(clientName, readonly, connectionPool) {
24 this.rolledBack = false;
25 this.transaction = new TransactionManager_1.Transaction();
26 this.clientName = clientName;
27 this.readonly = readonly;
28 this.connectionPool = connectionPool;
29 const labels = [clientName, readonly ? 'true' : 'false'];
30 this.transactionExecutionDurationsHistogram = transactionExecutionDurationsHistogram.labels(...labels);
31 this.rolledBackTransactionsCounter = rolledBackTransactionsCounter.labels(...labels);
32 }
33 async runQueryWithoutTransaction(sql, bindsArr) {
34 await this.obtainConnection();
35 try {
36 return await this.sanitizeAndRunQueryInConnection(sql, bindsArr);
37 }
38 finally {
39 this.releaseConnection();
40 }
41 }
42 getTransaction() {
43 return this.transaction;
44 }
45 async begin() {
46 this.timer = this.transactionExecutionDurationsHistogram.startTimer();
47 await this.obtainConnection();
48 await this.doTransactionBegin();
49 this.transaction.begin();
50 this.transaction.addCommitListener(() => this.doTransactionCommit());
51 this.transaction.addRollbackListener(() => this.doTransactionRollback());
52 this.transaction.addEndListener(() => this.releaseConnection());
53 }
54 async obtainConnection() {
55 this.connection = await this.connectionPool.getConnection();
56 }
57 query(sql, ...bindArrs) {
58 return this.sanitizeAndRunQueryInConnection(sql, bindArrs);
59 }
60 queryAssoc(sql, bindObj) {
61 return this.runQueryAssocPrivate(sql, bindObj);
62 }
63 markError(error) {
64 this.transaction.markError(error);
65 }
66 sanitizeAndRunQueryInConnection(sql, bindsArr) {
67 LOGGER.debug(`sql: ${sql} ${(bindsArr && (bindsArr.length > 0)) ? `| ${bindsArr}` : ''}`);
68 if (!Array.isArray(bindsArr)) {
69 bindsArr = [];
70 }
71 return this.runQueryInConnection(`/* Transaction Id ${this.transaction.id} */ ${sql}`, bindsArr);
72 }
73 runQueryAssocPrivate(sql, bindsObj) {
74 if (sql.indexOf('::') < 0 || !bindsObj) {
75 // tslint:disable-next-line:no-invalid-this
76 return this.sanitizeAndRunQueryInConnection.call(this, sql, []);
77 }
78 sql.replace(/::(\w)+::/g, (substr, key) => {
79 if (bindsObj.hasOwnProperty(key)) {
80 return bindsObj[key];
81 }
82 return substr;
83 });
84 }
85 doTransactionBegin() {
86 return this.sanitizeAndRunQueryInConnection(this.getTransactionBeginSQL());
87 }
88 // tslint:disable-next-line:prefer-function-over-method
89 getTransactionBeginSQL() {
90 return 'BEGIN';
91 }
92 doTransactionCommit() {
93 return this.sanitizeAndRunQueryInConnection(this.getTransactionCommitSQL());
94 }
95 // tslint:disable-next-line:prefer-function-over-method
96 getTransactionCommitSQL() {
97 return 'COMMIT';
98 }
99 doTransactionRollback() {
100 this.rolledBack = true;
101 this.rolledBackTransactionsCounter.inc();
102 return this.sanitizeAndRunQueryInConnection(this.getTransactionRollbackSQL());
103 }
104 // tslint:disable-next-line:prefer-function-over-method
105 getTransactionRollbackSQL() {
106 return 'ROLLBACK';
107 }
108 async releaseConnection() {
109 if (this.connection) {
110 this.connectionPool.release(this.connection);
111 this.connection = null;
112 }
113 }
114 async end() {
115 try {
116 await this.transaction.end();
117 }
118 finally {
119 if (this.timer) {
120 this.timer();
121 }
122 }
123 }
124 isRolledBack() {
125 return this.rolledBack;
126 }
127 isReadonly() {
128 return this.readonly;
129 }
130}
131exports.DBTransaction = DBTransaction;
132//# sourceMappingURL=DBTransaction.js.map
\No newline at end of file