Skip to content

Commit 3221920

Browse files
committed
fix: skip config validation when using connector
This changeset fixes a problem in the original custom `connector` factory method implementation that required the `server` config property to be defined even though its value is ignored. Removing the validation when `config.options.connector` is defined fixes the problem. Ref: #1540 Fixes: #1541 Signed-off-by: Ruy Adorno <ruyadorno@google.com>
1 parent e4eadf8 commit 3221920

File tree

2 files changed

+94
-12
lines changed

2 files changed

+94
-12
lines changed

src/connection.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ class Connection extends EventEmitter {
10521052
throw new TypeError('The "config" argument is required and must be of type Object.');
10531053
}
10541054

1055-
if (typeof config.server !== 'string') {
1055+
if (typeof config.server !== 'string' && !config.options!.connector) {
10561056
throw new TypeError('The "config.server" property is required and must be of type string.');
10571057
}
10581058

@@ -1343,8 +1343,15 @@ class Connection extends EventEmitter {
13431343
if (typeof config.options.connector !== 'function') {
13441344
throw new TypeError('The "config.options.connector" property must be a function.');
13451345
}
1346+
if (config.server) {
1347+
throw new Error('Server and connector are mutually exclusive, but ' + config.server + ' and a connector function were provided');
1348+
}
1349+
if (config.options.port) {
1350+
throw new Error('Port and connector are mutually exclusive, but ' + config.options.port + ' and a connector function were provided');
1351+
}
13461352

13471353
this.config.options.connector = config.options.connector;
1354+
this.config.options.port = undefined;
13481355
}
13491356

13501357
if (config.options.cryptoCredentialsDetails !== undefined) {
@@ -1900,7 +1907,10 @@ class Connection extends EventEmitter {
19001907
initialiseConnection() {
19011908
const signal = this.createConnectTimer();
19021909

1903-
if (this.config.options.port) {
1910+
if (this.config.options.connector) {
1911+
// port and multiSubnetFailover are not used when using a custom connector
1912+
return this.connectOnPort(0, false, signal, this.config.options.connector);
1913+
} else if (this.config.options.port) {
19041914
return this.connectOnPort(this.config.options.port, this.config.options.multiSubnetFailover, signal, this.config.options.connector);
19051915
} else {
19061916
return instanceLookup({
@@ -1995,7 +2005,12 @@ class Connection extends EventEmitter {
19952005
this.socket = socket;
19962006

19972007
this.closed = false;
1998-
this.debug.log('connected to ' + this.config.server + ':' + this.config.options.port);
2008+
2009+
const message =
2010+
'connected to ' + this.config.server + ':' + this.config.options.port;
2011+
const customConnectorMessage =
2012+
'connected via custom connector';
2013+
this.debug.log(customConnector ? customConnectorMessage : message);
19992014

20002015
this.sendPreLogin();
20012016
this.transitionTo(this.STATE.SENT_PRELOGIN);
@@ -2073,8 +2088,10 @@ class Connection extends EventEmitter {
20732088
*/
20742089
connectTimeout() {
20752090
const message = `Failed to connect to ${this.config.server}${this.config.options.port ? `:${this.config.options.port}` : `\\${this.config.options.instanceName}`} in ${this.config.options.connectTimeout}ms`;
2076-
this.debug.log(message);
2077-
this.emit('connect', new ConnectionError(message, 'ETIMEOUT'));
2091+
const customConnectorMessage = `Failed to connect using custom connector in ${this.config.options.connectTimeout}ms`;
2092+
const errMessage = this.config.options.connector ? customConnectorMessage : message;
2093+
this.debug.log(errMessage);
2094+
this.emit('connect', new ConnectionError(errMessage, 'ETIMEOUT'));
20782095
this.connectTimer = undefined;
20792096
this.dispatchEvent('connectTimeout');
20802097
}
@@ -2202,8 +2219,10 @@ class Connection extends EventEmitter {
22022219
socketError(error: Error) {
22032220
if (this.state === this.STATE.CONNECTING || this.state === this.STATE.SENT_TLSSSLNEGOTIATION) {
22042221
const message = `Failed to connect to ${this.config.server}:${this.config.options.port} - ${error.message}`;
2205-
this.debug.log(message);
2206-
this.emit('connect', new ConnectionError(message, 'ESOCKET'));
2222+
const customConnectorMessage = `Failed to connect using custom connector - ${error.message}`;
2223+
const errMessage = this.config.options.connector ? customConnectorMessage : message;
2224+
this.debug.log(errMessage);
2225+
this.emit('connect', new ConnectionError(errMessage, 'ESOCKET'));
22072226
} else {
22082227
const message = `Connection lost - ${error.message}`;
22092228
this.debug.log(message);
@@ -2228,15 +2247,21 @@ class Connection extends EventEmitter {
22282247
* @private
22292248
*/
22302249
socketClose() {
2231-
this.debug.log('connection to ' + this.config.server + ':' + this.config.options.port + ' closed');
2250+
const message = 'connection to ' + this.config.server + ':' + this.config.options.port + ' closed';
2251+
const customConnectorMessage = 'connection closed';
2252+
this.debug.log(this.config.options.connector ? customConnectorMessage : message);
22322253
if (this.state === this.STATE.REROUTING) {
2233-
this.debug.log('Rerouting to ' + this.routingData!.server + ':' + this.routingData!.port);
2254+
const message = 'Rerouting to ' + this.routingData!.server + ':' + this.routingData!.port;
2255+
const customConnectorMessage = 'Rerouting';
2256+
this.debug.log(this.config.options.connector ? customConnectorMessage : message);
22342257

22352258
this.dispatchEvent('reconnect');
22362259
} else if (this.state === this.STATE.TRANSIENT_FAILURE_RETRY) {
22372260
const server = this.routingData ? this.routingData.server : this.config.server;
22382261
const port = this.routingData ? this.routingData.port : this.config.options.port;
2239-
this.debug.log('Retry after transient failure connecting to ' + server + ':' + port);
2262+
const message = 'Retry after transient failure connecting to ' + server + ':' + port;
2263+
const customConnectorMessage = 'Retry after transient failure connecting';
2264+
this.debug.log(this.config.options.connector ? customConnectorMessage : message);
22402265

22412266
this.dispatchEvent('retry');
22422267
} else {

test/unit/custom-connector.js

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ describe('custom connector', function() {
2828
const host = server.address().address;
2929
const port = server.address().port;
3030
const connection = new Connection({
31-
server: host,
3231
options: {
3332
connector: async () => {
3433
customConnectorCalled = true;
@@ -37,7 +36,6 @@ describe('custom connector', function() {
3736
port,
3837
});
3938
},
40-
port
4139
},
4240
});
4341

@@ -59,4 +57,63 @@ describe('custom connector', function() {
5957

6058
connection.connect();
6159
});
60+
61+
it('should emit socket error custom connector msg', function(done) {
62+
const connection = new Connection({
63+
options: {
64+
connector: async () => {
65+
throw new Error('ERR');
66+
},
67+
},
68+
});
69+
70+
connection.connect((err) => {
71+
assert.strictEqual(
72+
err.code,
73+
'ESOCKET',
74+
'should emit expected error code'
75+
);
76+
assert.strictEqual(
77+
err.message,
78+
'Failed to connect using custom connector - ERR',
79+
'should emit expected custom connector error msg'
80+
);
81+
done();
82+
});
83+
});
84+
85+
it('should only accept functions', function(done) {
86+
assert.throws(() => {
87+
new Connection({
88+
options: {
89+
connector: 'foo',
90+
},
91+
});
92+
}, Error, 'The "config.options.connector" property must be a function.');
93+
done();
94+
});
95+
96+
it('should not allow setting both server and connector options', function(done) {
97+
assert.throws(() => {
98+
new Connection({
99+
server: '0.0.0.0',
100+
options: {
101+
connector: async () => {},
102+
},
103+
});
104+
}, Error, 'Server and connector are mutually exclusive, but 0.0.0.0 and a connector function were provided');
105+
done();
106+
});
107+
108+
it('should not allow setting both port and connector options', function(done) {
109+
assert.throws(() => {
110+
new Connection({
111+
options: {
112+
connector: async () => {},
113+
port: 8080,
114+
},
115+
});
116+
}, Error, 'Port and connector are mutually exclusive, but 8080 and a connector function were provided');
117+
done();
118+
});
62119
});

0 commit comments

Comments
 (0)