mythix-orm-postgresql 1.7.2 → 1.7.4
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/lib/postgresql-connection.js +63 -12
- package/package.json +1 -1
|
@@ -7,10 +7,18 @@ const Nife = require('nife');
|
|
|
7
7
|
const { DateTime } = require('luxon');
|
|
8
8
|
const PG = require('pg');
|
|
9
9
|
const PGFormat = require('pg-format');
|
|
10
|
-
const { Literals }
|
|
10
|
+
const { Literals, Errors } = require('mythix-orm');
|
|
11
11
|
const { SQLConnectionBase } = require('mythix-orm-sql-base');
|
|
12
12
|
const PostgreSQLQueryGenerator = require('./postgresql-query-generator');
|
|
13
13
|
|
|
14
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
15
|
+
|
|
16
|
+
function sleep(ms) {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
setTimeout(resolve, ms);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
class PostgreSQLConnection extends SQLConnectionBase {
|
|
15
23
|
static dialect = 'postgresql';
|
|
16
24
|
|
|
@@ -33,6 +41,27 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
33
41
|
return !!this.pool;
|
|
34
42
|
}
|
|
35
43
|
|
|
44
|
+
async getPoolConnection(_retryCount) {
|
|
45
|
+
let retryCount = _retryCount || 0;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
return await this.pool.connect();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
let options = this.getOptions();
|
|
51
|
+
let connectMaxRetries = (options.connectMaxRetries == null) ? 5 : options.connectMaxRetries;
|
|
52
|
+
let connectRetryDelay = (options.connectRetryDelay == null) ? 5000 : options.connectRetryDelay;
|
|
53
|
+
|
|
54
|
+
if (error.code === 'ECONNREFUSED') {
|
|
55
|
+
if (retryCount < connectMaxRetries) {
|
|
56
|
+
await sleep(connectRetryDelay);
|
|
57
|
+
return this.getPoolConnection(retryCount + 1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
throw new Errors.MythixORMConnectionTimedOutError(error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
36
65
|
async start() {
|
|
37
66
|
let options = this.getOptions();
|
|
38
67
|
|
|
@@ -45,11 +74,10 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
45
74
|
},
|
|
46
75
|
options,
|
|
47
76
|
{
|
|
48
|
-
statement_timeout: options.statementTimeout,
|
|
49
|
-
query_timeout: options.queryTimeout,
|
|
50
|
-
connectionTimeoutMillis: options.connectionTimeout,
|
|
77
|
+
statement_timeout: options.statementTimeout || DEFAULT_TIMEOUT_MS,
|
|
78
|
+
query_timeout: options.queryTimeout || DEFAULT_TIMEOUT_MS,
|
|
79
|
+
connectionTimeoutMillis: options.connectionTimeout || 60000,
|
|
51
80
|
idle_in_transaction_session_timeout: options.idleTransactionTimeout,
|
|
52
|
-
idleTimeoutMillis: options.idleConnectionTimeout,
|
|
53
81
|
max: options.maxPoolConnections,
|
|
54
82
|
},
|
|
55
83
|
);
|
|
@@ -73,6 +101,10 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
73
101
|
pool.on('remove', (client) => {
|
|
74
102
|
this.emit('disconnect', client);
|
|
75
103
|
});
|
|
104
|
+
|
|
105
|
+
// Ensure that we can connect to the DB
|
|
106
|
+
let client = await this.getPoolConnection();
|
|
107
|
+
await client.release();
|
|
76
108
|
}
|
|
77
109
|
|
|
78
110
|
async stop() {
|
|
@@ -141,7 +173,7 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
141
173
|
try {
|
|
142
174
|
client = _client || this.inTransaction;
|
|
143
175
|
if (!client) {
|
|
144
|
-
client = await this.
|
|
176
|
+
client = await this.getPoolConnection();
|
|
145
177
|
hasOwnClient = true;
|
|
146
178
|
}
|
|
147
179
|
|
|
@@ -155,8 +187,14 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
155
187
|
else
|
|
156
188
|
result = await client.query(sql);
|
|
157
189
|
|
|
190
|
+
if (client && hasOwnClient)
|
|
191
|
+
await client.release();
|
|
192
|
+
|
|
158
193
|
return this.formatResultsResponse(sql, result);
|
|
159
194
|
} catch (error) {
|
|
195
|
+
if (client && hasOwnClient)
|
|
196
|
+
await client.release();
|
|
197
|
+
|
|
160
198
|
if (logger) {
|
|
161
199
|
logger.error(error);
|
|
162
200
|
logger.error('QUERY: ', sql);
|
|
@@ -165,13 +203,10 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
165
203
|
error.query = sql;
|
|
166
204
|
|
|
167
205
|
throw error;
|
|
168
|
-
} finally {
|
|
169
|
-
if (client && hasOwnClient)
|
|
170
|
-
await client.release();
|
|
171
206
|
}
|
|
172
207
|
}
|
|
173
208
|
|
|
174
|
-
async transaction(callback, _options) {
|
|
209
|
+
async transaction(callback, _options, _retryCount) {
|
|
175
210
|
let options = _options || {};
|
|
176
211
|
let inheritedThis = Object.create(options.connection || this.getContextValue('connection', this));
|
|
177
212
|
let lockMode = inheritedThis.getLockMode(options.lock);
|
|
@@ -198,15 +233,31 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
198
233
|
}
|
|
199
234
|
|
|
200
235
|
if (!inheritedThis.inTransaction) {
|
|
201
|
-
client = inheritedThis.inTransaction = await inheritedThis.
|
|
236
|
+
client = inheritedThis.inTransaction = await inheritedThis.getPoolConnection();
|
|
237
|
+
|
|
238
|
+
let beginSuccess = false;
|
|
202
239
|
|
|
203
240
|
try {
|
|
204
241
|
await inheritedThis.query(`BEGIN${(options.beginArguments) ? ` ${options.beginArguments}` : ''}`, options, client);
|
|
242
|
+
beginSuccess = true;
|
|
243
|
+
|
|
205
244
|
if (lockStatement)
|
|
206
245
|
await inheritedThis.query(lockStatement, options, client);
|
|
207
246
|
|
|
208
247
|
// TODO: Need to handle "busy" error
|
|
209
248
|
} catch (error) {
|
|
249
|
+
if (beginSuccess)
|
|
250
|
+
await inheritedThis.query('ROLLBACK', options, client);
|
|
251
|
+
|
|
252
|
+
// Transaction timeout (deadlock)
|
|
253
|
+
if (error.query && (/LOCK TABLE/).test(error.query.text)) {
|
|
254
|
+
let retryCount = _retryCount || 0;
|
|
255
|
+
if (retryCount < 5) {
|
|
256
|
+
await client.release();
|
|
257
|
+
return this.transaction(callback, _options, retryCount + 1);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
210
261
|
await client.release();
|
|
211
262
|
throw error;
|
|
212
263
|
}
|
|
@@ -221,7 +272,7 @@ class PostgreSQLConnection extends SQLConnectionBase {
|
|
|
221
272
|
}
|
|
222
273
|
|
|
223
274
|
try {
|
|
224
|
-
let result = await inheritedThis.createContext(callback, inheritedThis, inheritedThis);
|
|
275
|
+
let result = await await inheritedThis.createContext(callback, inheritedThis, inheritedThis);
|
|
225
276
|
|
|
226
277
|
if (savePointName)
|
|
227
278
|
await inheritedThis.query(`RELEASE SAVEPOINT ${savePointName}`, options, client);
|