1 | // Copyright (c) 2016, 2024, Oracle and/or its affiliates.
|
2 |
|
3 | //-----------------------------------------------------------------------------
|
4 | //
|
5 | // This software is dual-licensed to you under the Universal Permissive License
|
6 | // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
|
7 | // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
|
8 | // either license.
|
9 | //
|
10 | // If you elect to accept the software under the Apache License, Version 2.0,
|
11 | // the following applies:
|
12 | //
|
13 | // Licensed under the Apache License, Version 2.0 (the "License");
|
14 | // you may not use this file except in compliance with the License.
|
15 | // You may obtain a copy of the License at
|
16 | //
|
17 | // https://www.apache.org/licenses/LICENSE-2.0
|
18 | //
|
19 | // Unless required by applicable law or agreed to in writing, software
|
20 | // distributed under the License is distributed on an "AS IS" BASIS,
|
21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22 | // See the License for the specific language governing permissions and
|
23 | // limitations under the License.
|
24 | //
|
25 | //-----------------------------------------------------------------------------
|
26 |
|
27 | ;
|
28 |
|
29 | const Connection = require('./connection.js');
|
30 | const EventEmitter = require('events');
|
31 | const constants = require('./constants.js');
|
32 | const errors = require('./errors.js');
|
33 | const settings = require('./settings.js');
|
34 | const nodbUtil = require('./util.js');
|
35 | const impl = require('./impl');
|
36 | const PoolStatistics = require('./poolStatistics.js');
|
37 |
|
38 |
|
39 | class Pool extends EventEmitter {
|
40 |
|
41 | constructor() {
|
42 | super();
|
43 | this._impl = new impl.PoolImpl();
|
44 | this._queueMax = 0;
|
45 | this._queueTimeout = 0;
|
46 | this._enableStatistics = false;
|
47 | this._timeOfReset = this._createdDate = Date.now();
|
48 | this._sessionCallback = undefined;
|
49 | this._connRequestQueue = [];
|
50 | this._connectionClass = settings.connectionClass;
|
51 | }
|
52 |
|
53 | //---------------------------------------------------------------------------
|
54 | // _checkPoolOpen()
|
55 | //
|
56 | // Check if the pool is open (not draining/reconfiguring/closed) and throw an
|
57 | // appropriate exception if not.
|
58 | //---------------------------------------------------------------------------
|
59 | _checkPoolOpen(ignoreReconfiguring) {
|
60 | if (this.status === constants.POOL_STATUS_DRAINING) {
|
61 | errors.throwErr(errors.ERR_POOL_CLOSING);
|
62 | } else if (this.status === constants.POOL_STATUS_CLOSED) {
|
63 | errors.throwErr(errors.ERR_POOL_CLOSED);
|
64 | } else if (!ignoreReconfiguring) {
|
65 | if (this.status === constants.POOL_STATUS_RECONFIGURING) {
|
66 | errors.throwErr(errors.ERR_POOL_RECONFIGURING);
|
67 | }
|
68 | }
|
69 | }
|
70 |
|
71 | //---------------------------------------------------------------------------
|
72 | // _checkRequestQueue()
|
73 | //
|
74 | // When a connection is returned to the pool, this method is called (via an
|
75 | // event handler) to determine when requests for connections should be
|
76 | // resumed and cancels any timeout that may have been associated with the
|
77 | // request. This method is also called from reconfigure() so that waiting
|
78 | // connection requests can be processed. Note the use of a local variable for
|
79 | // the number of connections out. This is because the connection requests will
|
80 | // not resume until after the loop is finished, and therefore the number of
|
81 | // connections the pool thinks is out will not be incremented.
|
82 | //---------------------------------------------------------------------------
|
83 | _checkRequestQueue() {
|
84 | let connectionsOut = this._connectionsOut;
|
85 | while (this._connRequestQueue.length > 0 && connectionsOut < this.poolMax) {
|
86 | connectionsOut += 1;
|
87 | const payload = this._connRequestQueue.shift();
|
88 | if (this._enableStatistics) {
|
89 | this._totalRequestsDequeued += 1;
|
90 | this._updateWaitStatistics(payload);
|
91 | }
|
92 | if (payload.timeoutHandle) {
|
93 | clearTimeout(payload.timeoutHandle);
|
94 | }
|
95 | // inform the waiter that processing can continue
|
96 | payload.resolve();
|
97 | }
|
98 | }
|
99 |
|
100 | //---------------------------------------------------------------------------
|
101 | // _enableStats (DEPRECATED)
|
102 | //
|
103 | // Property for whether statistics are enabled on the pool.
|
104 | //---------------------------------------------------------------------------
|
105 | get _enableStats() {
|
106 | return this._enableStatistics;
|
107 | }
|
108 |
|
109 | //---------------------------------------------------------------------------
|
110 | // _resetStatistics()
|
111 | // To initialize the counters/timers
|
112 | //---------------------------------------------------------------------------
|
113 | _resetStatistics() {
|
114 | this._timeOfReset = Date.now();
|
115 | this._totalConnectionRequests = 0;
|
116 | this._totalRequestsEnqueued = 0;
|
117 | this._totalRequestsDequeued = 0;
|
118 | this._totalFailedRequests = 0;
|
119 | this._totalRequestsRejected = 0;
|
120 | this._totalRequestTimeouts = 0;
|
121 | this._maximumQueueLength = this._connRequestQueue.length;
|
122 | this._totalTimeInQueue = 0;
|
123 | this._minTimeInQueue = 0;
|
124 | this._maxTimeInQueue = 0;
|
125 | }
|
126 |
|
127 | //---------------------------------------------------------------------------
|
128 | // _setup()
|
129 | //
|
130 | // Sets up the pool instance with additional attributes used for logging
|
131 | // statistics and managing the connection queue.
|
132 | //---------------------------------------------------------------------------
|
133 | _setup(options, poolAlias) {
|
134 | this._queueTimeout = options.queueTimeout;
|
135 | this._queueMax = options.queueMax;
|
136 | this._enableStatistics = options.enableStatistics;
|
137 | this._edition = options.edition;
|
138 | this._eventsFlag = options.events;
|
139 | this._externalAuth = options.externalAuth;
|
140 | this._homogeneous = options.homogeneous;
|
141 | this._user = options.user;
|
142 | this._connectString = options.connectString;
|
143 | this._status = constants.POOL_STATUS_OPEN;
|
144 | this._connectionsOut = 0;
|
145 | this._poolAlias = poolAlias;
|
146 |
|
147 | // register event handler for when request queue should be checked
|
148 | this.on('_checkRequestQueue', this._checkRequestQueue);
|
149 |
|
150 | this._resetStatistics();
|
151 |
|
152 | }
|
153 |
|
154 | //---------------------------------------------------------------------------
|
155 | // _updateWaitStatistics()
|
156 | //
|
157 | // Update pool wait statistics after a connect request has spent some time in
|
158 | // the queue.
|
159 | //---------------------------------------------------------------------------
|
160 | _updateWaitStatistics(payload) {
|
161 | const waitTime = Date.now() - payload.enqueuedTime;
|
162 | this._totalTimeInQueue += waitTime;
|
163 | if (this._minTimeInQueue === 0) {
|
164 | this._minTimeInQueue = waitTime;
|
165 | } else {
|
166 | this._minTimeInQueue = Math.min(this._minTimeInQueue, waitTime);
|
167 | }
|
168 | this._maxTimeInQueue = Math.max(this._maxTimeInQueue, waitTime);
|
169 | }
|
170 |
|
171 | //---------------------------------------------------------------------------
|
172 | // _verifyGetConnectionOptions()
|
173 | //
|
174 | // Verify the getConnection() options are acceptable. Performs any
|
175 | // transformations that are needed before returning the options to the
|
176 | // caller.
|
177 | //---------------------------------------------------------------------------
|
178 | _verifyGetConnectionOptions(options) {
|
179 |
|
180 | // define normalized options (value returned to caller)
|
181 | const outOptions = {};
|
182 |
|
183 | // only one of "user" and "username" may be specified (and must be strings)
|
184 | if (options.user !== undefined) {
|
185 | errors.assertParamPropValue(typeof options.user === 'string', 1, "user");
|
186 | outOptions.user = options.user;
|
187 | }
|
188 | if (options.username !== undefined) {
|
189 | errors.assert(outOptions.user === undefined, errors.ERR_DBL_USER);
|
190 | errors.assertParamPropValue(typeof options.username === 'string', 1,
|
191 | "username");
|
192 | outOptions.user = options.username;
|
193 | }
|
194 |
|
195 | if (this.externalAuth &&
|
196 | outOptions.user && (outOptions.user[0] !== '['
|
197 | || outOptions.user.slice(-1) !== ']')) {
|
198 | // username is not enclosed in [].
|
199 | errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
|
200 | }
|
201 |
|
202 | // password must be a string
|
203 | if (options.password !== undefined) {
|
204 | errors.assertParamPropValue(typeof options.password === 'string', 1,
|
205 | "password");
|
206 | if (this.externalAuth) {
|
207 | errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
|
208 | }
|
209 | outOptions.password = options.password;
|
210 | }
|
211 |
|
212 | // tag must be a string
|
213 | if (options.tag !== undefined) {
|
214 | errors.assertParamPropValue(typeof options.tag === 'string', 1, "tag");
|
215 | outOptions.tag = options.tag;
|
216 | }
|
217 |
|
218 | // matchAnyTag must be a boolean
|
219 | if (options.matchAnyTag !== undefined) {
|
220 | errors.assertParamPropValue(typeof options.matchAnyTag === 'boolean', 1,
|
221 | "matchAnyTag");
|
222 | outOptions.matchAnyTag = options.matchAnyTag;
|
223 | }
|
224 |
|
225 | // shardingKey must be an array of values
|
226 | if (options.shardingKey !== undefined) {
|
227 | const value = options.shardingKey;
|
228 | errors.assertParamPropValue(nodbUtil.isShardingKey(value), 1,
|
229 | "shardingKey");
|
230 | outOptions.shardingKey = options.shardingKey;
|
231 | }
|
232 |
|
233 | // superShardingKey must be an array of values
|
234 | if (options.superShardingKey !== undefined) {
|
235 | const value = options.superShardingKey;
|
236 | errors.assertParamPropValue(nodbUtil.isShardingKey(value), 1,
|
237 | "superShardingKey");
|
238 | outOptions.superShardingKey = options.superShardingKey;
|
239 | }
|
240 |
|
241 | return outOptions;
|
242 | }
|
243 |
|
244 | //---------------------------------------------------------------------------
|
245 | // close()
|
246 | //
|
247 | // Close the pool, optionally allowing for a period of time to pass for
|
248 | // connections to "drain" from the pool.
|
249 | //---------------------------------------------------------------------------
|
250 | async close(a1) {
|
251 | let drainTime = 0;
|
252 | let forceClose = false;
|
253 |
|
254 | // check arguments
|
255 | errors.assertArgCount(arguments, 0, 1);
|
256 | if (arguments.length == 1) {
|
257 |
|
258 | // drain time must be a valid number; timeouts larger than a 32-bit signed
|
259 | // integer are not supported
|
260 | errors.assertParamValue(typeof a1 === 'number', 1);
|
261 | if (a1 < 0 || isNaN(a1) || a1 > 2 ** 31) {
|
262 | errors.throwErr(errors.ERR_INVALID_PARAMETER_VALUE, 1);
|
263 | }
|
264 |
|
265 | // no need to worry about drain time if no connections are out!
|
266 | forceClose = true;
|
267 | if (this._connectionsOut > 0) {
|
268 | drainTime = a1 * 1000;
|
269 | }
|
270 |
|
271 | }
|
272 |
|
273 | // if the pool is draining/reconfiguring/closed, throw an appropriate error
|
274 | this._checkPoolOpen(false);
|
275 |
|
276 | // wait for the pool to become empty or for the drain timeout to expire
|
277 | // (whichever comes first)
|
278 | if (drainTime > 0) {
|
279 | this._status = constants.POOL_STATUS_DRAINING;
|
280 | await new Promise(resolve => {
|
281 | const timeout = setTimeout(() => {
|
282 | this.removeAllListeners('_allCheckedIn');
|
283 | resolve();
|
284 | }, drainTime);
|
285 | this.once('_allCheckedIn', () => {
|
286 | clearTimeout(timeout);
|
287 | resolve();
|
288 | });
|
289 | });
|
290 | }
|
291 |
|
292 | // if any connections are still out and the pool is not being force closed,
|
293 | // throw an exception
|
294 | if (!forceClose && this._connectionsOut > 0) {
|
295 | errors.throwErr(errors.ERR_POOL_HAS_BUSY_CONNECTIONS);
|
296 | }
|
297 |
|
298 | // close the pool
|
299 | await this._impl.close();
|
300 | this._status = constants.POOL_STATUS_CLOSED;
|
301 | this.emit('_afterPoolClose');
|
302 |
|
303 | }
|
304 |
|
305 | //---------------------------------------------------------------------------
|
306 | // connectionsInUse
|
307 | //
|
308 | // Property for the number of connections in use by the pool.
|
309 | //---------------------------------------------------------------------------
|
310 | get connectionsInUse() {
|
311 | return this._impl.getConnectionsInUse();
|
312 | }
|
313 |
|
314 | //---------------------------------------------------------------------------
|
315 | // connectionsOpen
|
316 | //
|
317 | // Property for the number of connections opened by the pool.
|
318 | //---------------------------------------------------------------------------
|
319 | get connectionsOpen() {
|
320 | return this._impl.getConnectionsOpen();
|
321 | }
|
322 |
|
323 | //---------------------------------------------------------------------------
|
324 | // connectString
|
325 | //
|
326 | // Property for the connect string used to create the pool.
|
327 | //---------------------------------------------------------------------------
|
328 | get connectString() {
|
329 | return this._connectString;
|
330 | }
|
331 |
|
332 | //---------------------------------------------------------------------------
|
333 | // thin()
|
334 | //
|
335 | // return true, if driver mode is thin while creating pool
|
336 | // return false, if driver mode is thick while creating pool
|
337 | //---------------------------------------------------------------------------
|
338 | get thin() {
|
339 | return settings.thin;
|
340 | }
|
341 |
|
342 | //---------------------------------------------------------------------------
|
343 | // edition
|
344 | //
|
345 | // Property for the edition used to create the pool.
|
346 | //---------------------------------------------------------------------------
|
347 | get edition() {
|
348 | return this._edition;
|
349 | }
|
350 |
|
351 | //---------------------------------------------------------------------------
|
352 | // enableStatistics
|
353 | //
|
354 | // Property for whether statistics are enabled on the pool.
|
355 | //---------------------------------------------------------------------------
|
356 | get enableStatistics() {
|
357 | return this._enableStatistics;
|
358 | }
|
359 |
|
360 | //---------------------------------------------------------------------------
|
361 | // events
|
362 | //
|
363 | // Property for the events flag value used to create the pool.
|
364 | //---------------------------------------------------------------------------
|
365 | get events() {
|
366 | return this._eventsFlag;
|
367 | }
|
368 |
|
369 | //---------------------------------------------------------------------------
|
370 | // externalAuth
|
371 | //
|
372 | // Property for the externalAuth flag value used to create the pool.
|
373 | //---------------------------------------------------------------------------
|
374 | get externalAuth() {
|
375 | return this._externalAuth;
|
376 | }
|
377 |
|
378 | //---------------------------------------------------------------------------
|
379 | // getConnection()
|
380 | //
|
381 | // Gets a connection from the pool and returns it to the caller. If there are
|
382 | // fewer connections out than the poolMax setting, then the request will
|
383 | // return immediately; otherwise, the request will be queued for up to
|
384 | // queueTimeout milliseconds.
|
385 | //---------------------------------------------------------------------------
|
386 | async getConnection(a1) {
|
387 | let poolMax;
|
388 | let options = {};
|
389 |
|
390 | // check arguments
|
391 | errors.assertArgCount(arguments, 0, 1);
|
392 | if (arguments.length == 1) {
|
393 | errors.assertParamValue(nodbUtil.isObject(a1), 1);
|
394 | options = this._verifyGetConnectionOptions(a1);
|
395 | }
|
396 |
|
397 | // get connection class value from pool
|
398 | options.connectionClass = this._connectionClass;
|
399 |
|
400 | // if pool is draining/closed, throw an appropriate error
|
401 | this._checkPoolOpen(true);
|
402 |
|
403 | // manage stats, if applicable
|
404 | if (this._enableStatistics) {
|
405 | this._totalConnectionRequests += 1;
|
406 | }
|
407 |
|
408 | // getting the poolMax setting on the pool may fail if the pool is no
|
409 | // longer valid
|
410 | try {
|
411 | poolMax = this.poolMax;
|
412 | } catch (err) {
|
413 | if (this._enableStatistics) {
|
414 | this._totalFailedRequests += 1;
|
415 | }
|
416 | throw err;
|
417 | }
|
418 |
|
419 | if (this._connectionsOut >= poolMax ||
|
420 | this.status === constants.POOL_STATUS_RECONFIGURING) {
|
421 |
|
422 | // when the queue is huge, throw error early without waiting for queue
|
423 | // timeout
|
424 | if (this._connRequestQueue.length >= this._queueMax &&
|
425 | this._queueMax >= 0) {
|
426 | if (this._enableStatistics) {
|
427 | this._totalRequestsRejected += 1;
|
428 | }
|
429 | errors.throwErr(errors.ERR_QUEUE_MAX_EXCEEDED, this._queueMax);
|
430 | }
|
431 |
|
432 | // if too many connections are out, wait until room is made available or
|
433 | // the queue timeout expires
|
434 | await new Promise((resolve, reject) => {
|
435 |
|
436 | // set up a payload which will be added to the queue for processing
|
437 | const payload = { resolve: resolve, reject: reject };
|
438 |
|
439 | // if using a queue timeout, establish the timeout so that when it
|
440 | // expires the payload will be removed from the queue and an exception
|
441 | // thrown
|
442 | if (this._queueTimeout !== 0) {
|
443 | payload.timeoutHandle = setTimeout(() => {
|
444 | const ix = this._connRequestQueue.indexOf(payload);
|
445 | if (ix >= 0) {
|
446 | this._connRequestQueue.splice(ix, 1);
|
447 | }
|
448 | if (this._enableStatistics) {
|
449 | this._totalRequestTimeouts += 1;
|
450 | this._updateWaitStatistics(payload);
|
451 | }
|
452 | try {
|
453 | errors.throwErr(errors.ERR_CONN_REQUEST_TIMEOUT,
|
454 | this._queueTimeout);
|
455 | } catch (err) {
|
456 | reject(err);
|
457 | }
|
458 | }, this._queueTimeout);
|
459 | }
|
460 |
|
461 | // add payload to the queue
|
462 | this._connRequestQueue.push(payload);
|
463 | if (this._enableStatistics) {
|
464 | payload.enqueuedTime = Date.now();
|
465 | this._totalRequestsEnqueued += 1;
|
466 | this._maximumQueueLength = Math.max(this._maximumQueueLength,
|
467 | this._connRequestQueue.length);
|
468 | }
|
469 |
|
470 | });
|
471 |
|
472 | // check if pool is draining/closed after delay has
|
473 | // completed and throw an appropriate error
|
474 | this._checkPoolOpen(true);
|
475 |
|
476 | }
|
477 |
|
478 | // room is available in the queue, so proceed to acquire a connection from
|
479 | // the pool; adjust the connections out immediately in order to ensure that
|
480 | // another attempt doesn't proceed while this one is underway
|
481 | this._connectionsOut += 1;
|
482 | try {
|
483 |
|
484 | // acquire connection from the pool
|
485 | const conn = new Connection();
|
486 | conn._impl = await this._impl.getConnection(options);
|
487 | conn._pool = this;
|
488 |
|
489 | // invoke tag fixup callback method if one has been specified and the
|
490 | // actual tag on the connection doesn't match the one requested, or the
|
491 | // connection is freshly created; if the callback fails, close the
|
492 | // connection and remove it from the pool
|
493 | const requestedTag = options.tag || "";
|
494 | if (typeof this.sessionCallback === 'function' &&
|
495 | (conn._impl._newSession || conn.tag != requestedTag)) {
|
496 | try {
|
497 | await new Promise((resolve, reject) => {
|
498 | this.sessionCallback(conn, requestedTag, function(err) {
|
499 | if (err) {
|
500 | reject(err);
|
501 | } else {
|
502 | resolve();
|
503 | }
|
504 | });
|
505 | });
|
506 | } catch (err) {
|
507 | await conn.close({ drop: true });
|
508 | throw err;
|
509 | }
|
510 | }
|
511 |
|
512 | // when connection is closed, check to see if another request should be
|
513 | // processed and update any stats, as needed
|
514 | conn.on('_afterConnClose', () => {
|
515 | this._connectionsOut -= 1;
|
516 | this.emit('_checkRequestQueue');
|
517 | if (this._connectionsOut == 0) {
|
518 | this.emit('_allCheckedIn');
|
519 | }
|
520 | });
|
521 |
|
522 | return (conn);
|
523 |
|
524 | } catch (err) {
|
525 | this._connectionsOut -= 1;
|
526 | if (this._enableStatistics) {
|
527 | this._totalFailedRequests += 1;
|
528 | }
|
529 | this.emit('_checkRequestQueue');
|
530 | throw err;
|
531 | }
|
532 |
|
533 | }
|
534 |
|
535 | //---------------------------------------------------------------------------
|
536 | // getStatistics()
|
537 | //
|
538 | // Method to obtain a JSON object with all statistical metrics and pool
|
539 | // properties
|
540 | //---------------------------------------------------------------------------
|
541 | getStatistics() {
|
542 | this._checkPoolOpen(false);
|
543 |
|
544 | if (this._enableStatistics !== true) {
|
545 | return null;
|
546 | }
|
547 | return new PoolStatistics(this);
|
548 | }
|
549 |
|
550 | //---------------------------------------------------------------------------
|
551 | // homogeneous
|
552 | //
|
553 | // Property for the homogeneous flag value used to create the pool.
|
554 | //---------------------------------------------------------------------------
|
555 | get homogeneous() {
|
556 | return this._homogeneous;
|
557 | }
|
558 |
|
559 | //---------------------------------------------------------------------------
|
560 | // logStatistics()
|
561 | //
|
562 | // Method to print statistical related information and pool related
|
563 | // information when enableStatistics is set to true.
|
564 | //
|
565 | // NOTE: This function replaces the DEPRECATED _logStats() function.
|
566 | //---------------------------------------------------------------------------
|
567 | logStatistics() {
|
568 | const stats = this.getStatistics();
|
569 | if (stats === null) {
|
570 | errors.throwErr(errors.ERR_POOL_STATISTICS_DISABLED);
|
571 | }
|
572 | stats.logStatistics();
|
573 | }
|
574 |
|
575 | //---------------------------------------------------------------------------
|
576 | // poolAlias
|
577 | //
|
578 | // Property for the alias assigned to the pool.
|
579 | // ---------------------------------------------------------------------------
|
580 | get poolAlias() {
|
581 | return this._poolAlias;
|
582 | }
|
583 |
|
584 | //---------------------------------------------------------------------------
|
585 | // poolIncrement
|
586 | //
|
587 | // Property for the number of connections to create each time the pool needs
|
588 | // to grow.
|
589 | // ---------------------------------------------------------------------------
|
590 | get poolIncrement() {
|
591 | return this._impl.getPoolIncrement();
|
592 | }
|
593 |
|
594 | //---------------------------------------------------------------------------
|
595 | // poolMax
|
596 | //
|
597 | // Property for the maximum number of connections allowed in the pool.
|
598 | //---------------------------------------------------------------------------
|
599 | get poolMax() {
|
600 | return this._impl.getPoolMax();
|
601 | }
|
602 |
|
603 | //---------------------------------------------------------------------------
|
604 | // poolMaxPerShard
|
605 | //
|
606 | // Property for the maximum number of connections allowed in the pool for
|
607 | // each shard.
|
608 | //---------------------------------------------------------------------------
|
609 | get poolMaxPerShard() {
|
610 | return this._impl.getPoolMaxPerShard();
|
611 | }
|
612 |
|
613 | //---------------------------------------------------------------------------
|
614 | // poolMin
|
615 | //
|
616 | // Property for the minimum number of connections allowed in the pool.
|
617 | //---------------------------------------------------------------------------
|
618 | get poolMin() {
|
619 | return this._impl.getPoolMin();
|
620 | }
|
621 |
|
622 | //---------------------------------------------------------------------------
|
623 | // poolPingInterval
|
624 | //
|
625 | // Property for the ping interval to use for the pool.
|
626 | //---------------------------------------------------------------------------
|
627 | get poolPingInterval() {
|
628 | return this._impl.getPoolPingInterval();
|
629 | }
|
630 |
|
631 | //---------------------------------------------------------------------------
|
632 | // poolPingTimeout
|
633 | //
|
634 | // Property for the ping timeout associated with the pool.
|
635 | //---------------------------------------------------------------------------
|
636 | get poolPingTimeout() {
|
637 | return this._impl.getPoolPingTimeout();
|
638 | }
|
639 |
|
640 | //---------------------------------------------------------------------------
|
641 | // poolTimeout
|
642 | //
|
643 | // Property for the timeout associated with the pool.
|
644 | //---------------------------------------------------------------------------
|
645 | get poolTimeout() {
|
646 | return this._impl.getPoolTimeout();
|
647 | }
|
648 |
|
649 | //---------------------------------------------------------------------------
|
650 | // queueMax
|
651 | //
|
652 | // Property for the maximum number of pending pool connections that can be
|
653 | // queued.
|
654 | //---------------------------------------------------------------------------
|
655 | get queueMax() {
|
656 | return this._queueMax;
|
657 | }
|
658 |
|
659 | //---------------------------------------------------------------------------
|
660 | // queueTimeout
|
661 | //
|
662 | // Property for the milliseconds a connection request can spend in the queue
|
663 | // before an exception is thrown.
|
664 | //---------------------------------------------------------------------------
|
665 | get queueTimeout() {
|
666 | return this._queueTimeout;
|
667 | }
|
668 |
|
669 | //---------------------------------------------------------------------------
|
670 | // reconfigure()
|
671 | //
|
672 | // Reconfigure the pool, change the value for given pool-properties.
|
673 | //---------------------------------------------------------------------------
|
674 | async reconfigure(options) {
|
675 |
|
676 | // check arguments
|
677 | errors.assertArgCount(arguments, 1, 1);
|
678 | errors.assertParamValue(nodbUtil.isObject(options));
|
679 | errors.assertParamPropUnsignedInt(options, 1, "queueMax");
|
680 | errors.assertParamPropUnsignedInt(options, 1, "queueTimeout");
|
681 | errors.assertParamPropBool(options, 1, "enableStatistics");
|
682 | errors.assertParamPropBool(options, 1, "resetStatistics");
|
683 | errors.assertParamPropUnsignedInt(options, 1, "poolMin");
|
684 | errors.assertParamPropUnsignedInt(options, 1, "poolMax");
|
685 | errors.assertParamPropUnsignedInt(options, 1, "poolMaxPerShard");
|
686 | errors.assertParamPropUnsignedInt(options, 1, "poolIncrement");
|
687 | errors.assertParamPropInt(options, 1, "poolPingInterval");
|
688 | errors.assertParamPropUnsignedInt(options, 1, "poolTimeout");
|
689 | errors.assertParamPropUnsignedInt(options, 1, "stmtCacheSize");
|
690 | errors.assertParamPropBool(options, 1, "sodaMetaDataCache");
|
691 |
|
692 | // reconfiguration can happen only when status is OPEN
|
693 | this._checkPoolOpen(false);
|
694 |
|
695 | this._status = constants.POOL_STATUS_RECONFIGURING;
|
696 | try {
|
697 | // poolMin/poolMax/poolIncrement/poolPingInterval/poolTimeout/
|
698 | // poolMaxPerShard/stmtCacheSize/sodaMetaDataCache parameters
|
699 | await this._impl.reconfigure(options);
|
700 |
|
701 | // pool JS parameters: queueMax, queueTimeout, enableStatistics,
|
702 | // resetStatistics
|
703 |
|
704 | // reset the statistics-metrics only if 'resetStatistics' is true or
|
705 | // 'enableStatistics' is being set to true
|
706 | if (options.resetStatistics == true ||
|
707 | (options.enableStatistics == true &&
|
708 | this._enableStatistics == false)) {
|
709 | this._resetStatistics();
|
710 | }
|
711 |
|
712 | if (options.queueMax !== undefined) {
|
713 | this._queueMax = options.queueMax;
|
714 | }
|
715 |
|
716 | if (options.queueTimeout !== undefined) {
|
717 | this._queueTimeout = options.queueTimeout;
|
718 | }
|
719 |
|
720 | if (options.enableStatistics !== undefined) {
|
721 | this._enableStatistics = options.enableStatistics;
|
722 | }
|
723 | } finally {
|
724 | this._status = constants.POOL_STATUS_OPEN;
|
725 | }
|
726 | this.emit('_checkRequestQueue');
|
727 | }
|
728 |
|
729 | //---------------------------------------------------------------------------
|
730 | // sessionCallback
|
731 | //
|
732 | // Property for the session callback associated with the pool.
|
733 | //---------------------------------------------------------------------------
|
734 | get sessionCallback() {
|
735 | return this._sessionCallback;
|
736 | }
|
737 |
|
738 | //---------------------------------------------------------------------------
|
739 | // setAccessToken()
|
740 | //
|
741 | // Set parameters for token based authentication.
|
742 | //---------------------------------------------------------------------------
|
743 | async setAccessToken(options) {
|
744 | errors.assertArgCount(arguments, 1, 1);
|
745 | errors.assertParamValue(nodbUtil.isObject(options), 1);
|
746 | errors.assertParamPropString(options, 1, "token");
|
747 | errors.assertParamPropString(options, 1, "privateKey");
|
748 | await this._impl.setAccessToken(options);
|
749 | }
|
750 |
|
751 | //---------------------------------------------------------------------------
|
752 | // sodaMetaDataCache
|
753 | //
|
754 | // Property for whether the SODA metadata cache is enabled or not.
|
755 | //---------------------------------------------------------------------------
|
756 | get sodaMetaDataCache() {
|
757 | return this._impl.getSodaMetaDataCache();
|
758 | }
|
759 |
|
760 | //---------------------------------------------------------------------------
|
761 | // status
|
762 | //
|
763 | // Property for the pool's status.
|
764 | //---------------------------------------------------------------------------
|
765 | get status() {
|
766 | return this._status;
|
767 | }
|
768 |
|
769 | //---------------------------------------------------------------------------
|
770 | // stmtCacheSize
|
771 | //
|
772 | // Property for the size of the statement cache to use when creating
|
773 | // connections in the pool.
|
774 | //---------------------------------------------------------------------------
|
775 | get stmtCacheSize() {
|
776 | return this._impl.getStmtCacheSize();
|
777 | }
|
778 |
|
779 | //---------------------------------------------------------------------------
|
780 | // user
|
781 | //
|
782 | // Property for the user used to create the pool.
|
783 | //---------------------------------------------------------------------------
|
784 | get user() {
|
785 | return this._user;
|
786 | }
|
787 |
|
788 | }
|
789 |
|
790 | Pool.prototype.close = nodbUtil.callbackify(Pool.prototype.close);
|
791 | Pool.prototype.getConnection = nodbUtil.callbackify(Pool.prototype.getConnection);
|
792 | Pool.prototype.reconfigure = nodbUtil.callbackify(Pool.prototype.reconfigure);
|
793 | Pool.prototype.setAccessToken = nodbUtil.callbackify(Pool.prototype.setAccessToken);
|
794 |
|
795 | // DEPRECATED aliases
|
796 | Pool.prototype.terminate = Pool.prototype.close;
|
797 | Pool.prototype._logStats = Pool.prototype.logStatistics;
|
798 |
|
799 | module.exports = Pool;
|