Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
dbec5f0
feat: implement COM_RESET_CONNECTION command
sidorares Mar 3, 2026
929830b
feat: add resetOnRelease pool option for automatic connection state c…
sidorares Mar 3, 2026
e93c260
fix: resolve TypeScript and linting errors in tests
sidorares Mar 3, 2026
7ac4d77
fix: disable resetOnRelease for timing-sensitive existing tests
sidorares Mar 3, 2026
2b3793c
fix: resolve remaining TypeScript type assertion errors
sidorares Mar 3, 2026
31b516c
fix: remove 'any' type and fix formatting in pool reset test
sidorares Mar 3, 2026
3f0f476
fix: make reset() resolve with void to match Promise<void> typing
sidorares Mar 3, 2026
6572f05
fix: address Copilot and wellwelwel review feedback
sidorares Mar 3, 2026
80c85be
fix: add missing resetOnRelease parameter to test helper getConfig()
sidorares Mar 4, 2026
e944918
fix: add TypeScript type cast for resetOnRelease in getConfig()
sidorares Mar 4, 2026
6632ff7
Merge branch 'master' into feature/reset-connection
wellwelwel Mar 5, 2026
1868b56
Merge branch 'master' into feature/reset-connection
wellwelwel Mar 8, 2026
13fd4e5
Merge branch 'master' into feature/reset-connection
wellwelwel Mar 11, 2026
bd2a22a
Merge branch 'master' into feature/reset-connection
wellwelwel Mar 15, 2026
d353b5f
Merge branch 'master' into feature/reset-connection
wellwelwel Mar 15, 2026
62e0594
fix: make resetOnRelease default to false to avoid breaking change
sidorares Apr 10, 2026
660be19
fix: address review feedback in reset connection tests
sidorares Apr 10, 2026
e63aa51
Merge branch 'master' into feature/reset-connection
sidorares Apr 10, 2026
dc8da19
docs: add reset connection and resetOnRelease documentation
sidorares Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/base/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,10 @@ class BaseConnection extends EventEmitter {
return this.addCommand(new Commands.Ping(cb));
}

reset(cb) {
return this.addCommand(new Commands.ResetConnection(cb));
}

_registerSlave(opts, cb) {
return this.addCommand(new Commands.RegisterSlave(opts, cb));
}
Expand Down
32 changes: 31 additions & 1 deletion lib/base/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,37 @@ class BasePool extends EventEmitter {
cb = this._connectionQueue.shift();
process.nextTick(this.getConnection.bind(this, cb));
}
} else if (this._connectionQueue.length) {
return;
}

// Reset connection state if configured
if (this.config.resetOnRelease && connection.reset) {
connection.reset((err) => {
if (err) {
// If reset fails, remove connection from pool
connection._pool = null;
spliceConnection(this._allConnections, connection);
connection.destroy();

// Try to create a new connection for waiting callbacks
if (this._connectionQueue.length) {
cb = this._connectionQueue.shift();
process.nextTick(this.getConnection.bind(this, cb));
}
return;
}

// Reset successful, continue with normal release flow
this._handleSuccessfulRelease(connection);
});
} else {
this._handleSuccessfulRelease(connection);
}
}

_handleSuccessfulRelease(connection) {
let cb;
if (this._connectionQueue.length) {
cb = this._connectionQueue.shift();
process.nextTick(() => {
connection._released = false;
Expand Down
2 changes: 2 additions & 0 deletions lib/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const Ping = require('./ping.js');
const RegisterSlave = require('./register_slave.js');
const BinlogDump = require('./binlog_dump.js');
const ChangeUser = require('./change_user.js');
const ResetConnection = require('./reset_connection.js');
const Quit = require('./quit.js');

module.exports = {
Expand All @@ -23,5 +24,6 @@ module.exports = {
RegisterSlave,
BinlogDump,
ChangeUser,
ResetConnection,
Quit,
};
29 changes: 29 additions & 0 deletions lib/commands/reset_connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

const Command = require('./command');
const Packets = require('../packets/index.js');

class ResetConnection extends Command {
constructor(callback) {
super();
this.onResult = callback;
}

start(packet, connection) {
const req = new Packets.ResetConnection();
connection.writePacket(req.toPacket());
return ResetConnection.prototype.resetConnectionResponse;
}

resetConnectionResponse(packet, connection) {
if (connection._statements) {
connection._statements.clear();
}
if (this.onResult) {
process.nextTick(this.onResult.bind(this, null));
}
return null;
}
}

module.exports = ResetConnection;
1 change: 1 addition & 0 deletions lib/constants/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ module.exports = {
STMT_FETCH: 0x1c,
DAEMON: 0x1d, // deprecated
BINLOG_DUMP_GTID: 0x1e,
RESET_CONNECTION: 0x1f, // introduced in 5.7.3
UNKNOWN: 0xff, // bad!
};
2 changes: 2 additions & 0 deletions lib/packets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const PrepareStatement = require('./prepare_statement');
const PreparedStatementHeader = require('./prepared_statement_header');
const Query = require('./query');
const RegisterSlave = require('./register_slave');
const ResetConnection = require('./reset_connection');
const ResultSetHeader = require('./resultset_header');
const SSLRequest = require('./ssl_request');
const TextRow = require('./text_row');
Expand All @@ -48,6 +49,7 @@ const ctorMap = {
PreparedStatementHeader,
Query,
RegisterSlave,
ResetConnection,
ResultSetHeader,
SSLRequest,
TextRow,
Expand Down
17 changes: 17 additions & 0 deletions lib/packets/reset_connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');

class ResetConnection {
constructor() {}

toPacket() {
const packet = new Packet(0, Buffer.alloc(5), 0, 5);
packet.offset = 4;
packet.writeInt8(CommandCodes.RESET_CONNECTION);
return packet;
}
}

module.exports = ResetConnection;
4 changes: 4 additions & 0 deletions lib/pool_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ class PoolConfig {
this.queueLimit = isNaN(options.queueLimit)
? 0
: Number(options.queueLimit);
this.resetOnRelease =
options.resetOnRelease === undefined
? false
: Boolean(options.resetOnRelease);
}
}

Expand Down
19 changes: 19 additions & 0 deletions lib/promise/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,25 @@ class PromiseConnection extends EventEmitter {
});
}

reset() {
const c = this.connection;
const localErr = new Error();
return new this.Promise((resolve, reject) => {
c.reset((err) => {
if (err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
reject(localErr);
} else {
resolve();
}
});
});
}

connect() {
const c = this.connection;
const localErr = new Error();
Expand Down
2 changes: 2 additions & 0 deletions promise.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export declare class Connection extends QueryableAndExecutableBase {

ping(): Promise<void>;

reset(): Promise<void>;

beginTransaction(): Promise<void>;

commit(): Promise<void>;
Expand Down
3 changes: 2 additions & 1 deletion test/common.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const waitDatabaseReady = function (callback: () => void) {
tryConnect();
};

export const getConfig = function (input?: ConnectionOptions) {
export const getConfig = function (input?: ConnectionOptions | PoolOptions) {
const args = input || {};
const params = {
host: args.host || config.host,
Expand All @@ -177,6 +177,7 @@ export const getConfig = function (input?: ConnectionOptions) {
connectionLimit: args && args.connectionLimit,
maxIdle: args && args.maxIdle,
idleTimeout: args && args.idleTimeout,
resetOnRelease: args && (args as PoolOptions).resetOnRelease,
jsonStrings: args && args.jsonStrings,
disableEval,
gracefulEnd: args && args.gracefulEnd,
Expand Down
Loading
Loading