From 603ee720a7c6befdea635fa2280b2fb302d139bc Mon Sep 17 00:00:00 2001 From: Vivek R Date: Sun, 12 Mar 2017 15:26:01 +0530 Subject: [PATCH 1/3] Added auto reconnection feature for WebSocket client --- README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ticker.js | 52 +++++++++++++++++++++++++++++++++++++++++---------- package.json | 2 +- 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e6c6eda..82e5d52 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,57 @@ Getting started WebSocket client ticker.setMode(ticker.modeFull, items); } +Auto reconnect WebSocket client +------------------------------- +``` +Available from version 1.2 +``` +Optionally you can enable client side auto reconnection to automatically reconnect if the connection is dropped. +It is very useful at times when client side network is unreliable and patchy. + +All you need to do is enale auto reconnection with preferred interval and time. For example + + // Enable autoreonnect with 5 second interval and retry for maximum of 20 times. + ticker.autoReconnect(true, 20, 5) + + // You can also set reconnection times to -1 for inifinite reconnections + ticker.autoReconnect(true, -1, 5) + +- Event `reconnecting` is called when auto reconnection is triggered and event callback carries two additionl params `reconnection interval set` and `current reconnection count`. + +- Event `noreconnect` is called when number of auto reconnections exceeds the maximum reconnection count set. For example if maximum reconnection count is set as `20` then after 20th reconnection this event will be triggered. + +- Event `connect` will be triggered again when reconnection succeeds. + +Here is an example demonstrating auto reconnection. + + var KiteTicker = require("kiteconnect").KiteTicker; + var ticker = new KiteTicker(api_key, user_id, public_token); + + // set autoreconnect with 10 maximum reconnections and 5 second interval + ticker.autoReconnect(true, 10, 5) + ticker.connect(); + ticker.on("tick", setTick); + ticker.on("connect", subscribe); + + ticker.on("noreconnect", function() { + console.log("noreconnect") + }); + + ticker.on("reconnecting", function(reconnect_interval, reconnections) { + console.log("Reconnecting: attempe - ", reconnections, " innterval - ", reconnect_interval); + }); + + function setTick(ticks) { + console.log("Ticks", ticks); + } + + function subscribe() { + var items = [738561]; + ticker.subscribe(items); + ticker.setMode(ticker.modeFull, items); + } + A typical web application ------------------------- In a typical web application where a new instance of diff --git a/lib/ticker.js b/lib/ticker.js index de2436e..7a92145 100644 --- a/lib/ticker.js +++ b/lib/ticker.js @@ -159,7 +159,7 @@ var KiteTicker = function(api_key, user_id, public_token, address) { reconnect_timer = null, auto_reconnect = false, reconnections = 0, - id = null, + currentWsUrl = null, token_modes = {}; // segment constants @@ -175,17 +175,22 @@ var KiteTicker = function(api_key, user_id, public_token, address) { /** * Auto reconnect settings - * @param {bool} Enable or disable auto disconnect. - * @param {number} [times=5] Number of times to retry. + * @param {bool} Enable or disable auto disconnect, defaults to false + * @param {number} [times=5] Number of times to retry, defaults to 5. Set -1 for infinite reconnections. + * @param {number} [times=5] Timeout in seconds, default to 5. * @memberOf KiteTicker * @method autoReconnect */ - this.autoReconnect = function(t, times) { + this.autoReconnect = function(t, times, timeout) { auto_reconnect = (t == true ? true : false); if(times) { reconnect_tries = times; } + + if(timeout) { + reconnect_interval = timeout; + } }; /** @@ -199,10 +204,20 @@ var KiteTicker = function(api_key, user_id, public_token, address) { return; } - ws = new WebSocket(address + "?api_key=" + api_key + "&user_id=" + user_id + "&public_token=" + public_token); + ws = new WebSocket(address + "?api_key=" + api_key + "&user_id=" + user_id + + "&public_token=" + public_token + "&uid=" + (new Date().getTime().toString())); ws.binaryType = "arraybuffer"; ws.onopen = function() { + // Store current open connection url to check for auto reconnection + if (!currentWsUrl) { + currentWsUrl = this.url + } + + // Reset reconnections attempt + reconnections = 0 + + // Trigger onconnect event trigger("connect"); // If there isn't an incoming message in n seconds, assume disconnection. @@ -211,7 +226,11 @@ var KiteTicker = function(api_key, user_id, public_token, address) { last_read = new Date(); read_timer = setInterval(function() { if((new Date() - last_read ) / 1000 >= read_timeout) { - id = null; + // reset currentWsUrl incase current connection timesout + // This is determined by the last heart beat received time + // exceeds read_timeout value + currentWsUrl = null; + if(ws) { ws.close(); } @@ -233,14 +252,23 @@ var KiteTicker = function(api_key, user_id, public_token, address) { } } + // Set last readtime to check for connection timeout last_read = new Date(); }; ws.onerror = function(e) { - ws.close(); + if(this && this.readyState == this.OPEN) { + this.close(); + } }; ws.onclose = function(e) { + // the ws id doesn't match the current global id, + // meaning it's a ghost close event. just ignore. + if(currentWsUrl && (this.url != currentWsUrl)) { + return; + } + triggerDisconnect(); }; }; @@ -278,7 +306,7 @@ var KiteTicker = function(api_key, user_id, public_token, address) { * connect - when connection is successfully established. * tick - when ticks are available (Arrays of `ticks` object as the first argument). * disconnect - when socket connction is disconnected. - * reconnecting - When reconnecting (Reconnecting interval as first argument). + * reconnecting - When reconnecting (Reconnecting interval and current reconnetion count as arguments respectively). * noreconnect - When reconnection fails after n number times. * ~~~~ * @@ -358,6 +386,10 @@ var KiteTicker = function(api_key, user_id, public_token, address) { function triggerDisconnect() { ws = null; trigger("disconnect"); + + if(auto_reconnect) { + attemptReconnection(); + } } // send a message via the socket @@ -501,12 +533,12 @@ var KiteTicker = function(api_key, user_id, public_token, address) { function attemptReconnection() { // Try reconnecting only so many times. - if(reconnections > reconnect_tries) { + if(reconnect_tries !== -1 && reconnections >= reconnect_tries) { trigger("noreconnect"); return; } - trigger("reconnecting", [reconnect_interval]); + trigger("reconnecting", [reconnect_interval, reconnections]); reconnect_timer = setTimeout(function() { self.connect(); }, reconnect_interval * 1000); diff --git a/package.json b/package.json index 4a0809a..4a40096 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kiteconnect", - "version": "1.1.1", + "version": "1.2", "description": "The official JS client library for the Kite Connect trading APIs", "main": "./lib/", "scripts": { From db555c259a9c9201ac714b99b7a2a664c2531cf3 Mon Sep 17 00:00:00 2001 From: Vivek R Date: Sun, 12 Mar 2017 16:04:52 +0530 Subject: [PATCH 2/3] Fixed typos and exit on noreconnect --- README.md | 12 ++++++------ lib/ticker.js | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 82e5d52..592ab98 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Getting started WebSocket client ticker.setMode(ticker.modeFull, items); } -Auto reconnect WebSocket client +Auto re-connect WebSocket client ------------------------------- ``` Available from version 1.2 @@ -85,17 +85,17 @@ Available from version 1.2 Optionally you can enable client side auto reconnection to automatically reconnect if the connection is dropped. It is very useful at times when client side network is unreliable and patchy. -All you need to do is enale auto reconnection with preferred interval and time. For example +All you need to do is enable auto reconnection with preferred interval and time. For example - // Enable autoreonnect with 5 second interval and retry for maximum of 20 times. + // Enable auto reconnect with 5 second interval and retry for maximum of 20 times. ticker.autoReconnect(true, 20, 5) // You can also set reconnection times to -1 for inifinite reconnections ticker.autoReconnect(true, -1, 5) -- Event `reconnecting` is called when auto reconnection is triggered and event callback carries two additionl params `reconnection interval set` and `current reconnection count`. +- Event `reconnecting` is called when auto reconnection is triggered and event callback carries two additional params `reconnection interval set` and `current reconnection count`. -- Event `noreconnect` is called when number of auto reconnections exceeds the maximum reconnection count set. For example if maximum reconnection count is set as `20` then after 20th reconnection this event will be triggered. +- Event `noreconnect` is called when number of auto reconnections exceeds the maximum reconnection count set. For example if maximum reconnection count is set as `20` then after 20th reconnection this event will be triggered. Also note that the current process is exited when this event is triggered. - Event `connect` will be triggered again when reconnection succeeds. @@ -115,7 +115,7 @@ Here is an example demonstrating auto reconnection. }); ticker.on("reconnecting", function(reconnect_interval, reconnections) { - console.log("Reconnecting: attempe - ", reconnections, " innterval - ", reconnect_interval); + console.log("Reconnecting: attempet - ", reconnections, " innterval - ", reconnect_interval); }); function setTick(ticks) { diff --git a/lib/ticker.js b/lib/ticker.js index 7a92145..3afede0 100644 --- a/lib/ticker.js +++ b/lib/ticker.js @@ -124,7 +124,7 @@ var KiteTicker = function(api_key, user_id, public_token, address) { mClearCache = 14, // public constants - modeFull = "full", // Full quote inluding market depth. 164 bytes. + modeFull = "full", // Full quote including market depth. 164 bytes. modeQuote = "quote", // Quote excluding market depth. 52 bytes. modeLTP = "ltp"; @@ -226,8 +226,8 @@ var KiteTicker = function(api_key, user_id, public_token, address) { last_read = new Date(); read_timer = setInterval(function() { if((new Date() - last_read ) / 1000 >= read_timeout) { - // reset currentWsUrl incase current connection timesout - // This is determined by the last heart beat received time + // reset currentWsUrl incase current connection times out + // This is determined when last heart beat received time interval // exceeds read_timeout value currentWsUrl = null; @@ -252,7 +252,7 @@ var KiteTicker = function(api_key, user_id, public_token, address) { } } - // Set last readtime to check for connection timeout + // Set last read time to check for connection timeout last_read = new Date(); }; @@ -535,7 +535,7 @@ var KiteTicker = function(api_key, user_id, public_token, address) { // Try reconnecting only so many times. if(reconnect_tries !== -1 && reconnections >= reconnect_tries) { trigger("noreconnect"); - return; + process.exit(1); } trigger("reconnecting", [reconnect_interval, reconnections]); From f0613ac235d7c1a4652377e3ea6cf39b2a488f1b Mon Sep 17 00:00:00 2001 From: Vivek R Date: Sun, 12 Mar 2017 16:11:16 +0530 Subject: [PATCH 3/3] Added auto reconnect example to ticker class description --- lib/ticker.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/ticker.js b/lib/ticker.js index 3afede0..6658090 100644 --- a/lib/ticker.js +++ b/lib/ticker.js @@ -93,7 +93,57 @@ var WebSocket = require("ws"); * }] * } * }, ...] - * +Auto re-connect WebSocket client +------------------------------- +``` +Available from version 1.2 +``` +Optionally you can enable client side auto reconnection to automatically reconnect if the connection is dropped. +It is very useful at times when client side network is unreliable and patchy. + +All you need to do is enable auto reconnection with preferred interval and time. For example + + // Enable auto reconnect with 5 second interval and retry for maximum of 20 times. + ticker.autoReconnect(true, 20, 5) + + // You can also set reconnection times to -1 for inifinite reconnections + ticker.autoReconnect(true, -1, 5) + +- Event `reconnecting` is called when auto reconnection is triggered and event callback carries two additional params `reconnection interval set` and `current reconnection count`. + +- Event `noreconnect` is called when number of auto reconnections exceeds the maximum reconnection count set. For example if maximum reconnection count is set as `20` then after 20th reconnection this event will be triggered. Also note that the current process is exited when this event is triggered. + +- Event `connect` will be triggered again when reconnection succeeds. + +Here is an example demonstrating auto reconnection. + + var KiteTicker = require("kiteconnect").KiteTicker; + var ticker = new KiteTicker(api_key, user_id, public_token); + + // set autoreconnect with 10 maximum reconnections and 5 second interval + ticker.autoReconnect(true, 10, 5) + ticker.connect(); + ticker.on("tick", setTick); + ticker.on("connect", subscribe); + + ticker.on("noreconnect", function() { + console.log("noreconnect") + }); + + ticker.on("reconnecting", function(reconnect_interval, reconnections) { + console.log("Reconnecting: attempet - ", reconnections, " innterval - ", reconnect_interval); + }); + + function setTick(ticks) { + console.log("Ticks", ticks); + } + + function subscribe() { + var items = [738561]; + ticker.subscribe(items); + ticker.setMode(ticker.modeFull, items); + } + * * @constructor * @name KiteTicker