Skip to content

Commit de806a1

Browse files
committed
Fix connection close by server treatment by WebSocket channels (#684)
The lack of set channel._open to false when the onclose event is triggered was causing the channel be broken without the other parts of the driver notice. In tbis way, a next iteration trying to get the broken connection will succeded in the try and run the query will result in a eternal pending promise. Mark the channel as closed enable the pool to discard and create a new connection if it needed.
1 parent 194c28e commit de806a1

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

src/internal/browser/browser-channel.js

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export default class WebSocketChannel {
6565
if (e && !e.wasClean) {
6666
self._handleConnectionError()
6767
}
68+
self._open = false
6869
}
6970
this._ws.onopen = function () {
7071
// Connected! Cancel the connection timeout

test/internal/browser/browser-channel.test.js

+24-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { SERVICE_UNAVAILABLE } from '../../../src/error'
2323
import { setTimeoutMock } from '../timers-util'
2424
import { ENCRYPTION_OFF, ENCRYPTION_ON } from '../../../src/internal/util'
2525
import ServerAddress from '../../../src/internal/server-address'
26-
import { read } from 'fs'
2726

2827
const WS_CONNECTING = 0
2928
const WS_OPEN = 1
@@ -266,17 +265,39 @@ describe('#unit WebSocketChannel', () => {
266265
}
267266
}
268267

268+
it('should set _open to false when connection closes', async () => {
269+
const fakeSetTimeout = setTimeoutMock.install()
270+
try {
271+
// do not execute setTimeout callbacks
272+
fakeSetTimeout.pause()
273+
const address = ServerAddress.fromUrl('bolt://localhost:8989')
274+
const driverConfig = { connectionTimeout: 4242 }
275+
const channelConfig = new ChannelConfig(
276+
address,
277+
driverConfig,
278+
SERVICE_UNAVAILABLE
279+
)
280+
webSocketChannel = new WebSocketChannel(
281+
channelConfig,
282+
undefined,
283+
createWebSocketFactory(WS_OPEN)
284+
)
285+
webSocketChannel._ws.close()
286+
expect(webSocketChannel._open).toBe(false)
287+
} finally {
288+
fakeSetTimeout.uninstall()
289+
}
290+
})
291+
269292
function createWebSocketFactory (readyState) {
270293
const ws = {}
271-
272294
ws.readyState = readyState
273295
ws.close = () => {
274296
ws.readyState = WS_CLOSED
275297
if (ws.onclose && typeof ws.onclose === 'function') {
276298
ws.onclose({ wasClean: true })
277299
}
278300
}
279-
280301
return url => {
281302
ws.url = url
282303
return ws

0 commit comments

Comments
 (0)