-
Notifications
You must be signed in to change notification settings - Fork 464
/
connection-pool.js
139 lines (125 loc) · 4.52 KB
/
connection-pool.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
'use strict'
const tds = require('tedious')
const debug = require('debug')('mssql:tedi')
const BaseConnectionPool = require('../base/connection-pool')
const { IDS } = require('../utils')
const shared = require('../shared')
const ConnectionError = require('../error/connection-error')
class ConnectionPool extends BaseConnectionPool {
_poolCreate () {
return new shared.Promise((resolve, reject) => {
const resolveOnce = (v) => {
resolve(v)
resolve = reject = () => {}
}
const rejectOnce = (e) => {
reject(e)
resolve = reject = () => {}
}
const cfg = {
server: this.config.server,
options: Object.assign({
encrypt: typeof this.config.encrypt === 'boolean' ? this.config.encrypt : true,
trustServerCertificate: typeof this.config.trustServerCertificate === 'boolean' ? this.config.trustServerCertificate : false
}, this.config.options),
authentication: Object.assign({
type: this.config.domain !== undefined ? 'ntlm' : 'default',
options: {
userName: this.config.user,
password: this.config.password,
domain: this.config.domain
}
}, this.config.authentication)
}
cfg.options.database = cfg.options.database || this.config.database
cfg.options.port = cfg.options.port || this.config.port
cfg.options.connectTimeout = cfg.options.connectTimeout ?? this.config.connectionTimeout ?? this.config.timeout ?? 15000
cfg.options.requestTimeout = cfg.options.requestTimeout ?? this.config.requestTimeout ?? this.config.timeout ?? 15000
cfg.options.tdsVersion = cfg.options.tdsVersion || '7_4'
cfg.options.rowCollectionOnDone = cfg.options.rowCollectionOnDone || false
cfg.options.rowCollectionOnRequestCompletion = cfg.options.rowCollectionOnRequestCompletion || false
cfg.options.useColumnNames = cfg.options.useColumnNames || false
cfg.options.appName = cfg.options.appName || 'node-mssql'
// tedious always connect via tcp when port is specified
if (cfg.options.instanceName) delete cfg.options.port
if (isNaN(cfg.options.requestTimeout)) cfg.options.requestTimeout = 15000
if (cfg.options.requestTimeout === Infinity || cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0
if (!cfg.options.debug && this.config.debug) {
cfg.options.debug = {
packet: true,
token: true,
data: true,
payload: true
}
}
let tedious
try {
tedious = new tds.Connection(cfg)
} catch (err) {
rejectOnce(err)
return
}
tedious.connect(err => {
if (err) {
err = new ConnectionError(err)
return rejectOnce(err)
}
debug('connection(%d): established', IDS.get(tedious))
this.collation = tedious.databaseCollation
resolveOnce(tedious)
})
IDS.add(tedious, 'Connection')
debug('pool(%d): connection #%d created', IDS.get(this), IDS.get(tedious))
debug('connection(%d): establishing', IDS.get(tedious))
tedious.on('end', () => {
const err = new ConnectionError('The connection ended without ever completing the connection')
rejectOnce(err)
})
tedious.on('error', err => {
if (err.code === 'ESOCKET') {
tedious.hasError = true
} else {
this.emit('error', err)
}
rejectOnce(err)
})
if (this.config.debug) {
tedious.on('debug', this.emit.bind(this, 'debug', tedious))
}
if (typeof this.config.beforeConnect === 'function') {
this.config.beforeConnect(tedious)
}
})
}
_poolValidate (tedious) {
if (tedious && !tedious.closed && !tedious.hasError) {
return !this.config.validateConnection || new shared.Promise((resolve) => {
const req = new tds.Request('SELECT 1;', (err) => {
resolve(!err)
})
tedious.execSql(req)
})
}
return false
}
_poolDestroy (tedious) {
return new shared.Promise((resolve, reject) => {
if (!tedious) {
resolve()
return
}
debug('connection(%d): destroying', IDS.get(tedious))
if (tedious.closed) {
debug('connection(%d): already closed', IDS.get(tedious))
resolve()
} else {
tedious.once('end', () => {
debug('connection(%d): destroyed', IDS.get(tedious))
resolve()
})
tedious.close()
}
})
}
}
module.exports = ConnectionPool