만약 fastify 사용 중 fastify.close
를 사용하면 callback이나 promise가 리턴되지않는 에러를 마주한다면 한번 확인해 봐야 하는 부분이 있다.
이 경우 @fastify/websocket
을 사용하는지 확인해 봐야 한다.
@fastify/websocket
, fastify-websocket
플러그인 사용 중 소켓에 달린 이벤트 리스너를 삭제하면 에러가 일어난다.
다만 이 경우 에러 핸들링이 되지도 않고 fastify.close
를 호출하면 바로 알 수 없는 종료와 함께 콜백도, 프로미스도 리턴되지 않는다.
즉 다음과 같은 코드를 실행한 후 fastify.close
를 호출하면 원인 추론이 힘들 버그가 생겨난다.
import Fastify from "fastify";
import FastifyWebsocket from "@fastify/websocket";
import WebSocket from "ws";
const fastify = Fastify()
await fastify.register(FastifyWebsocket)
//
fastify.get('/ws', { websocket: true }, (socket, rep) => {
socket.socket.removeAllListeners('close') // it make error
socket.destroy()
})
await fastify.listen(3000)
// websocket
const ws = new WebSocket("ws://localhost:3000/ws")
ws.onopen = () => {
console.log('websocket open')
ws.close()
}
await new Promise(resolve => {
ws.onclose = () => {
console.log('websocket closed')
resolve()
}
})
try {
// error expected
await fastify.close()
} catch {
console.log('closed') // 이걸 트리거하지 못함
}
console.log('closed') // 이것 역시 마찬가지.
아마 저수준 소켓의 close 이벤트에 자원 정리 관련한 코드가 심어져 있어서 생기는 것으로 추측되는데, readme.md에는 딱히 관련된 주의사항이 없었던 것 같다.(물론 대충봐서 그럴수도 있는데 좀 더 확인해보고 메인테이너한테 얘기해 보는 게 좋을 것 같다.)
만약 나와 같이 fastify
사용중 웹소켓 서버를 닫을 때 예상치 못하게 바로 끝나는 상황을 마주치면 코드 중 위와 같이 핸들러를 삭제하는 코드가 있는지 확인해 보자.