react-use-websocket icon indicating copy to clipboard operation
react-use-websocket copied to clipboard

heartbeat seems not working as expected

Open harikt opened this issue 10 months ago • 1 comments

Hey,

I have been experimenting with the heartbeat feature and as reported on comment https://github.com/robtaussig/react-use-websocket/pull/206#issuecomment-1867894798 , this seems not sending any messages via websocket.

const {
	sendMessage,
	sendJsonMessage,
	lastJsonMessage,
	readyState,
	getWebSocket,
} = useWebSocket(socketUrl, {
	onClose: (event) => {  console.log("onClose : " + event) },
	onError: (event) => {  console.log("onError : " + event) },
	onOpen: () => {
		console.log("Connection opened.");		
	},
	// share: true,
	skipAssert: true,
	retryOnError: true,
	//Will attempt to reconnect on all close events, such as server shutting down
	shouldReconnect: (closeEvent) => {
		return true;
	},
	// Defaults to 20, so increased to 10000
	reconnectAttempts: 10000,
	//attemptNumber will be 0 the first time it attempts to reconnect, so this equation results in a reconnect pattern of 1 second, 2 seconds, 4 seconds, 8 seconds, and then caps at 10 seconds until the maximum number of attempts is reached
	reconnectInterval: (attemptNumber) => {
		const maxTime = 300; // Maximum time for reconnection
		const baseTime = 2; // Base time for exponential backoff

		// Calculate reconnect time using exponential backoff
		const reconnectTime = Math.min(maxTime, Math.pow(baseTime, attemptNumber)) * 1000;

		console.log("Reconnect attempt will be made in : " + reconnectTime + " ms");

		return reconnectTime;
	},
	// Default
	heartbeat: true,
}, connect);

Option 2 for heartbeat

heartbeat: {
	message: 'ping',
	returnMessage: 'pong',
	timeout: 60000, // 1 minute, if no response is received, the connection will be closed
	interval: 2500, // every 25 seconds, a ping message will be sent
},

Option 3 for heartbeat

heartbeat: {
    message: function () {
    	return JSON.stringify({
    		type: 'ping'
    	});
    },
    
    returnMessage: function () {
    	return JSON.stringify({
    		status: 'success',
    		message: 'pong',
    	});
    },
    timeout: 60000, // 1 minute, if no response is received, the connection will be closed
    interval: 2500, // every 25 seconds, a ping message will be sent
}

Note : You can see one of the option I choose is skipAssert: true, . This was because of error I was getting

app.js:22773 Uncaught (in promise) Error
    at assertIsWebSocket (app.js:22773:17)
    at bindCloseHandler (app.js:22836:38)
    at attachListeners (app.js:22897:34)
    at createOrJoinSocket (app.js:23097:56)
    at app.js:23507:85
    at step (app.js:23387:25)
    at Object.next (app.js:23334:20)
    at fulfilled (app.js:23305:30)

image

So using skipAssert: true, has fixed the error. The note probably is another issue I should open.

harikt avatar Mar 26 '24 14:03 harikt

As an alternative approach this is what I did. If this helps anyone.

// Ping every 60 second
const HEARTBEAT_INTERVAL = 60000;

useEffect(() => {
	// Start heartbeat interval
	const heartbeatInterval = setInterval(() => {
		sendJsonMessage({
			type: 'ping'
		});
	}, HEARTBEAT_INTERVAL);

	// Clean up interval on component unmount
	return () => clearInterval(heartbeatInterval);
}, [sendJsonMessage]);

harikt avatar Mar 26 '24 14:03 harikt