안녕하세요. Caver Websocket관련 도움이 필요합니다.
현재 토큰 컨트랙트에서 발생한 입출금 관련 이벤트들을 조회할 목적으로 웹소켓을 사용하고 있습니다.
어플리케이션 서버를 동작시킨 바로 직후에는 통신도 매우 잘되고 이벤트들 받아오는 것도 이상없이 동작하는데 문제는, 아무 액션 없이 2분 정도 뒤에 다시 호출하면 에러가 발생한다는 점입니다.
첨부한 사진은 에러가 나는 부분을 캡쳐한 부분인데요, 콘솔에 출력해서 확인해본 에러 메시지 또한 아래 기재해드립니다.
connection not open on send()
Error: connection not open. try reconnect..
at WebsocketProvider.send (/home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-core-requestmanager/caver-providers-ws/src/index.js:258:18)
at /home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-core-requestmanager/src/index.js:132:64
at RequestManager.send (/home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-core-requestmanager/src/index.js:125:58)
at /home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-core-method/src/index.js:420:34
at /home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-core-method/src/index.js:435:9
at Contract.getPastEvents (/home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-contract/src/index.js:829:12)
at /home/webdev/cryptobric-api/routers/history.js:91:13
at Layer.handle [as handle_request] (/home/webdev/cryptobric-api/node_modules/express/lib/router/layer.js:95:5)
at next (/home/webdev/cryptobric-api/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/webdev/cryptobric-api/node_modules/express/lib/router/route.js:112:3)
at WebsocketProvider.send (/home/webdev/cryptobric-api/node_modules/caver-js/packages/caver-core-requestmanager/caver-providers-ws/src/index.js:258:18) 에러가 짚어준 코드를 살펴보았는데... 아무래도 reconnect 부분이 제대로 동작하고 있지 않은 것 같습니다.
참고 사항으로 해당 reconnect 코드 부분의 이전과 이후에 다음과 같이 콘솔 로그로 출력하는 부분을 넣어 디버깅 한 결과도 기재해드립니다.
WebsocketProvider.prototype.send = function(payload, callback) {
const _this = this
if (this.connection.readyState === this.connection.CONNECTING) {
setTimeout(function() {
_this.send(payload, callback)
}, 10)
return
}
// try reconnect, when connection is gone
// if(!this.connection.writable)
// this.connection.connect({url: this.url});
if (this.connection.readyState !== this.connection.OPEN) {
console.error('connection not open on send()')
console.log(typeof this.connection.onerror);
if (typeof this.connection.onerror === 'function') {
this.connection.onerror(new Error('connection not open'))
} else {
console.error('no error callback')
}
// reconnect
console.log(this.connection);
console.log('try reconnect')
this.connection = this.reconnect()
console.log('reconnect finished')
console.log(this.connection);
callback(new Error('connection not open. try reconnect..'))
return
}
this.connection.send(JSON.stringify(payload))
this._addResponseCallback(payload, callback)
}
reconnect 전에 출력한 웹소켓 내용은 아래와 같습니다.
W3CWebSocket {
_listeners: {},
addEventListener: [Function: _addEventListener],
removeEventListener: [Function: _removeEventListener],
dispatchEvent: [Function: _dispatchEvent],
_url: 'wss://api.baobab.klaytn.net:8652',
_readyState: 3,
_protocol: undefined,
_extensions: [],
_bufferedAmount: 0,
_binaryType: 'arraybuffer',
_connection: WebSocketConnection {
_debug: [Function: debug] {
namespace: 'websocket:connection',
enabled: false,
useColors: true,
color: 2,
inspectOpts: {},
printOutput: [Function (anonymous)]
},
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
_pingListenerCount: 0,
config: {
maxReceivedFrameSize: 1048576,
maxReceivedMessageSize: 8388608,
fragmentOutgoingMessages: true,
fragmentationThreshold: 16384,
webSocketVersion: 13,
assembleFragments: true,
disableNagleAlgorithm: true,
closeTimeout: 5000,
tlsOptions: {}
},
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'api.baobab.klaytn.net',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 11,
connecting: false,
_hadError: false,
_parent: null,
_host: 'api.baobab.klaytn.net',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: null,
_peername: [Object],
timeout: 0,
write: [Function: writeAfterFIN],
[Symbol(res)]: null,
[Symbol(asyncId)]: 6,
[Symbol(kHandle)]: null,
[Symbol(kSetNoDelay)]: true,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 391148,
[Symbol(kBytesWritten)]: 18521,
[Symbol(connect-options)]: [Object]
},
protocol: undefined,
extensions: [],
remoteAddress: '54.180.51.111',
closeReasonCode: 1006,
closeDescription: 'Connection dropped by remote peer.',
closeEventEmitted: true,
maskOutgoingPackets: true,
maskBytes: <Buffer d9 87 f0 3a>,
frameHeader: <Buffer 81 7e 08 38 01 00 00 00 40 b7>,
bufferList: BufferList {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
encoding: undefined,
length: [Getter],
write: [Function (anonymous)],
end: [Function (anonymous)],
push: [Function (anonymous)],
forEach: [Function (anonymous)],
join: [Function (anonymous)],
joinInto: [Function (anonymous)],
advance: [Function (anonymous)],
take: [Function (anonymous)],
toString: [Function (anonymous)],
[Symbol(kCapture)]: false
},
currentFrame: WebSocketFrame {
maskBytes: <Buffer d9 87 f0 3a>,
frameHeader: <Buffer 81 7e 08 38 01 00 00 00 40 b7>,
config: [Object],
maxReceivedFrameSize: 1048576,
protocolError: false,
frameTooLarge: false,
invalidCloseFrameLength: false,
parseState: 1,
closeStatus: -1
},
fragmentationSize: 0,
frameQueue: [],
connected: false,
state: 'closed',
waitingForCloseResponse: false,
receivedEnd: true,
closeTimeout: 5000,
assembleFragments: true,
maxReceivedMessageSize: 8388608,
outputBufferFull: false,
inputPaused: false,
receivedDataHandler: [Function: bound ],
_closeTimerHandler: [Function: bound ],
webSocketVersion: 13,
socketHadError: false,
[Symbol(kCapture)]: false
},
_client: WebSocketClient {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
config: {
maxReceivedFrameSize: 1048576,
maxReceivedMessageSize: 8388608,
fragmentOutgoingMessages: true,
fragmentationThreshold: 16384,
webSocketVersion: 13,
assembleFragments: true,
disableNagleAlgorithm: true,
closeTimeout: 5000,
tlsOptions: {}
},
_req: null,
protocols: [],
origin: undefined,
url: Url {
protocol: 'wss:',
slashes: true,
auth: null,
host: 'api.baobab.klaytn.net:8652',
port: '8652',
hostname: 'api.baobab.klaytn.net',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'wss://api.baobab.klaytn.net:8652/'
},
secure: true,
base64nonce: 'RgF/2pU93/ttTqQtxRvhSw==',
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'api.baobab.klaytn.net',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 11,
connecting: false,
_hadError: false,
_parent: null,
_host: 'api.baobab.klaytn.net',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: null,
_peername: [Object],
timeout: 0,
write: [Function: writeAfterFIN],
[Symbol(res)]: null,
[Symbol(asyncId)]: 6,
[Symbol(kHandle)]: null,
[Symbol(kSetNoDelay)]: true,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 391148,
[Symbol(kBytesWritten)]: 18521,
[Symbol(connect-options)]: [Object]
},
response: IncomingMessage {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
socket: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: true,
url: '',
method: null,
statusCode: 101,
statusMessage: 'Switching Protocols',
client: [TLSSocket],
_consuming: false,
_dumped: false,
[Symbol(kCapture)]: false
},
firstDataChunk: null,
[Symbol(kCapture)]: false
},
onerror: [Function (anonymous)],
onclose: [Function (anonymous)],
onmessage: [Function (anonymous)]
}
reconnect 이후 출력한 웹소켓 내용은 아래와 같습니다.
W3CWebSocket {
_listeners: {},
addEventListener: [Function: _addEventListener],
removeEventListener: [Function: _removeEventListener],
dispatchEvent: [Function: _dispatchEvent],
_url: 'wss://api.baobab.klaytn.net:8652',
_readyState: 0,
_protocol: undefined,
_extensions: '',
_bufferedAmount: 0,
_binaryType: 'arraybuffer',
_connection: undefined,
_client: WebSocketClient {
_events: [Object: null prototype] {
connect: [Function (anonymous)],
connectFailed: [Function (anonymous)]
},
_eventsCount: 2,
_maxListeners: undefined,
config: {
maxReceivedFrameSize: 1048576,
maxReceivedMessageSize: 8388608,
fragmentOutgoingMessages: true,
fragmentationThreshold: 16384,
webSocketVersion: 13,
assembleFragments: true,
disableNagleAlgorithm: true,
closeTimeout: 5000,
tlsOptions: {}
},
_req: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
outputData: [Array],
outputSize: 165,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: null,
_header: 'GET / HTTP/1.1\r\n' +
'Upgrade: websocket\r\n' +
'Connection: Upgrade\r\n' +
'Sec-WebSocket-Version: 13\r\n' +
'Sec-WebSocket-Key: 1VrcNXMmrND6WRONckZZXQ==\r\n' +
'Host: api.baobab.klaytn.net:8652\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/',
_ended: false,
res: null,
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
protocols: [],
origin: undefined,
url: Url {
protocol: 'wss:',
slashes: true,
auth: null,
host: 'api.baobab.klaytn.net:8652',
port: '8652',
hostname: 'api.baobab.klaytn.net',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'wss://api.baobab.klaytn.net:8652/'
},
secure: true,
base64nonce: '1VrcNXMmrND6WRONckZZXQ==',
[Symbol(kCapture)]: false
}
}
긴 내용의 에러임에도 불구하고 끝까지 읽어주셔서 감사합니다.
문의 내용을 요약드리자면 “Websocket의 reconnect 부분이 불완전한 것 같은데 어떻게 보완할 수 있을까요?” 입니다. ㅠㅠ 도와주십쇼.