mythix-orm-postgresql 1.7.1 → 1.7.3

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.
@@ -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 } = require('mythix-orm');
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.pool.connect();
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,33 @@ class PostgreSQLConnection extends SQLConnectionBase {
198
233
  }
199
234
 
200
235
  if (!inheritedThis.inTransaction) {
201
- client = inheritedThis.inTransaction = await inheritedThis.pool.connect();
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);
205
- if (lockStatement)
242
+ beginSuccess = true;
243
+
244
+ if (lockStatement) {
245
+ console.log('LOCK STATEMENT: ', lockStatement);
206
246
  await inheritedThis.query(lockStatement, options, client);
247
+ }
207
248
 
208
249
  // TODO: Need to handle "busy" error
209
250
  } catch (error) {
251
+ if (beginSuccess)
252
+ await inheritedThis.query('ROLLBACK', options, client);
253
+
254
+ // Transaction timeout (deadlock)
255
+ if (error.query && (/LOCK TABLE/).test(error.query.text)) {
256
+ let retryCount = _retryCount || 0;
257
+ if (retryCount < 5) {
258
+ await client.release();
259
+ return this.transaction(callback, _options, retryCount + 1);
260
+ }
261
+ }
262
+
210
263
  await client.release();
211
264
  throw error;
212
265
  }
@@ -221,7 +274,7 @@ class PostgreSQLConnection extends SQLConnectionBase {
221
274
  }
222
275
 
223
276
  try {
224
- let result = await inheritedThis.createContext(callback, inheritedThis, inheritedThis);
277
+ let result = await await inheritedThis.createContext(callback, inheritedThis, inheritedThis);
225
278
 
226
279
  if (savePointName)
227
280
  await inheritedThis.query(`RELEASE SAVEPOINT ${savePointName}`, options, client);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mythix-orm-postgresql",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "PostgreSQL driver for Mythix ORM",
5
5
  "main": "lib/index.js",
6
6
  "type": "commonjs",
@@ -33,8 +33,8 @@
33
33
  },
34
34
  "homepage": "https://github.com/th317erd/mythix-orm-postgresql#readme",
35
35
  "peerDependencies": {
36
- "mythix-orm": "^1.8.1",
37
- "mythix-orm-sql-base": "^1.7.1"
36
+ "mythix-orm": "^1.8.2",
37
+ "mythix-orm-sql-base": "^1.7.2"
38
38
  },
39
39
  "dependencies": {
40
40
  "luxon": "^3.0.4",