Skip to content

Commit 30e89fc

Browse files
committed
Fix connection close by server treatment by WebSocket channels (neo4j#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 694b9ea commit 30e89fc

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
@@ -244,17 +243,39 @@ describe('#unit WebSocketChannel', () => {
244243
}
245244
}
246245

246+
it('should set _open to false when connection closes', async () => {
247+
const fakeSetTimeout = setTimeoutMock.install()
248+
try {
249+
// do not execute setTimeout callbacks
250+
fakeSetTimeout.pause()
251+
const address = ServerAddress.fromUrl('bolt://localhost:8989')
252+
const driverConfig = { connectionTimeout: 4242 }
253+
const channelConfig = new ChannelConfig(
254+
address,
255+
driverConfig,
256+
SERVICE_UNAVAILABLE
257+
)
258+
webSocketChannel = new WebSocketChannel(
259+
channelConfig,
260+
undefined,
261+
createWebSocketFactory(WS_OPEN)
262+
)
263+
webSocketChannel._ws.close()
264+
expect(webSocketChannel._open).toBe(false)
265+
} finally {
266+
fakeSetTimeout.uninstall()
267+
}
268+
})
269+
247270
function createWebSocketFactory (readyState) {
248271
const ws = {}
249-
250272
ws.readyState = readyState
251273
ws.close = () => {
252274
ws.readyState = WS_CLOSED
253275
if (ws.onclose && typeof ws.onclose === 'function') {
254276
ws.onclose({ wasClean: true })
255277
}
256278
}
257-
258279
return url => {
259280
ws.url = url
260281
return ws

0 commit comments

Comments
 (0)