mssql 12.2.3 → 12.3.0

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/README.md CHANGED
@@ -133,6 +133,7 @@ const config = {
133
133
  ### Connections
134
134
 
135
135
  * [Pool Management](#pool-management)
136
+ * [Connection Validation](#connection-validation)
136
137
  * [ConnectionPool](#connections-1)
137
138
  * [connect](#connect-callback)
138
139
  * [close](#close)
@@ -574,6 +575,30 @@ sql.query('SELECT * FROM [example]').then((result) => {
574
575
  })
575
576
  ```
576
577
 
578
+ ### Connection Validation
579
+
580
+ When a connection is acquired from the pool, it can be validated to ensure it is still usable. This is controlled by the `validateConnection` config option.
581
+
582
+ ```javascript
583
+ const config = {
584
+ server: 'localhost',
585
+ // ...
586
+ validateConnection: true // default
587
+ }
588
+ ```
589
+
590
+ The following values are supported:
591
+
592
+ | Value | Description |
593
+ |---|---|
594
+ | `true` (default) | Executes `SELECT 1` against the connection before handing it to the caller. This is the most thorough check — it verifies end-to-end connectivity — but adds a round-trip query for every pool acquisition. |
595
+ | `'socket'` | Performs a lightweight, synchronous check of the underlying connection state and TCP socket health. No SQL query is executed. This is significantly cheaper at scale and catches most failure modes (closed connections, destroyed sockets, wrong protocol state), but will not detect issues like server-side session invalidation. **Tedious driver only** — with msnodesqlv8, this value falls back to `SELECT 1` behaviour because native ODBC connections do not expose socket-level properties. |
596
+ | `false` | Disables validation entirely. The connection is assumed to be healthy if it has not been flagged as closed or errored. Use this only if your application already handles stale connection errors gracefully. |
597
+
598
+ #### When to use `'socket'` mode
599
+
600
+ If your application maintains a large connection pool and you see high volumes of `SELECT 1` queries in your SQL Server monitoring, switching to `'socket'` mode can dramatically reduce overhead. TCP keepalive (enabled by default in tedious at 30-second intervals) will independently detect and close dead connections over time, so the socket-level check provides a good balance between reliability and performance.
601
+
577
602
  ## Configuration
578
603
 
579
604
  The following is an example configuration object:
@@ -608,6 +633,7 @@ const config = {
608
633
  - **pool.min** - The minimum of connections there can be in the pool (default: `0`).
609
634
  - **pool.idleTimeoutMillis** - The Number of milliseconds before closing an unused connection (default: `30000`).
610
635
  - **arrayRowMode** - Return row results as a an array instead of a keyed object. Also adds `columns` array. (default: `false`) See [Handling Duplicate Column Names](#handling-duplicate-column-names)
636
+ - **validateConnection** - Controls how connections are validated when acquired from the pool. See [Connection Validation](#connection-validation) for details. (default: `true`)
611
637
 
612
638
  Complete list of pool options can be found [here](https://github.com/vincit/tarn.js/#usage).
613
639
 
@@ -117,15 +117,36 @@ class ConnectionPool extends BaseConnectionPool {
117
117
  }
118
118
 
119
119
  _poolValidate (tedious) {
120
- if (tedious && !tedious.closed && !tedious.hasError) {
121
- return !this.config.validateConnection || new shared.Promise((resolve) => {
122
- const req = new tds.Request('SELECT 1;', (err) => {
123
- resolve(!err)
124
- })
125
- tedious.execSql(req)
126
- })
120
+ if (!tedious || tedious.closed || tedious.hasError) {
121
+ return false
122
+ }
123
+
124
+ const mode = this.config.validateConnection
125
+
126
+ if (!mode) {
127
+ return true
128
+ }
129
+
130
+ // Socket-level validation: check connection state and socket health
131
+ // without executing a SQL query. Much cheaper than SELECT 1 at scale.
132
+ if (mode === 'socket') {
133
+ if (tedious.state !== tedious.STATE.LOGGED_IN) {
134
+ return false
135
+ }
136
+ if (!tedious.socket || tedious.socket.destroyed || !tedious.socket.writable) {
137
+ return false
138
+ }
139
+ return true
127
140
  }
128
- return false
141
+
142
+ // SQL-level validation (default): execute SELECT 1 to verify the
143
+ // connection is fully functional end-to-end.
144
+ return new shared.Promise((resolve) => {
145
+ const req = new tds.Request('SELECT 1;', (err) => {
146
+ resolve(!err)
147
+ })
148
+ tedious.execSql(req)
149
+ })
129
150
  }
130
151
 
131
152
  _poolDestroy (tedious) {
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "azure",
22
22
  "node-mssql"
23
23
  ],
24
- "version": "12.2.3",
24
+ "version": "12.3.0",
25
25
  "main": "index.js",
26
26
  "type": "commonjs",
27
27
  "repository": {