Skip to content

Commit

Permalink
small improvement that enables as to add Conn.reconnectTries field an…
Browse files Browse the repository at this point in the history
…d wasReconnected(): boolean method to check if a connection is a result of a reconnection - same as the go server side #2
  • Loading branch information
kataras committed Jun 26, 2019
1 parent d339394 commit 91eb944
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 79 deletions.
10 changes: 7 additions & 3 deletions _examples/browserify/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ async function runExample() {
const conn = await neffos.dial(wsURL, {
default: { // "default" namespace.
_OnNamespaceConnected: function (nsConn, msg) {
if (nsConn.conn.wasReconnected()) {
addMessage("re-connected after " + nsConn.conn.reconnectTries.toString() + " trie(s)");
}

addMessage("connected to namespace: " + msg.Namespace);
handleNamespaceConnectedConn(nsConn);
},
Expand All @@ -53,9 +57,9 @@ async function runExample() {
// if > 0 then on network failures it tries to reconnect every 5 seconds, defaults to 0 (disabled).
reconnect: 5000,
// custom headers:
headers: {
// 'X-Username': 'kataras',
}
// headers: {
// 'X-Username': 'kataras'
// }
});

// You can either wait to conenct or just conn.connect("connect")
Expand Down
2 changes: 1 addition & 1 deletion _examples/browserify/bundle.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions _examples/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ func server(upgrader neffos.Upgrader) {
// }

srv.OnConnect = func(c *neffos.Conn) error {
if c.WasReconnected() {
log.Printf("[%s] connection is a result of a client-side re-connection, with tries: %d", c.ID(), c.ReconnectTries)
}

if dissalowAll {
return fmt.Errorf("you are not allowed to connect here for some reason")
}
Expand Down Expand Up @@ -120,10 +124,6 @@ func server(upgrader neffos.Upgrader) {
}

srv.OnUpgradeError = func(err error) {
if retries, ok := neffos.IsTryingToReconnect(err); ok {
log.Printf("a client was tried to reconnect %d times\n", retries)
return
}
log.Printf("ERROR: %v", err)
}

Expand Down
86 changes: 54 additions & 32 deletions dist/neffos.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/neffos.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/neffos.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "neffos.js",
"version": "0.1.14",
"version": "0.1.15",
"description": "javascript client for the modern neffos websocket framework",
"keywords": [
"neffos",
Expand Down
104 changes: 68 additions & 36 deletions src/neffos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,24 +680,6 @@ function parseHeadersAsURLParameters(headers: Headers, url: string): string {
return url;
}

function makeWebsocketConnection(endpoint: string, options?: Options | any) {
if (isBrowser) {
if (!isNull(options)) {
if (options.headers) {
endpoint = parseHeadersAsURLParameters(options.headers, endpoint);
}

if (options.protocols) {
return new WebSocket(endpoint, options.protocols);
} else {
return new WebSocket(endpoint)
}
}
}

return new WebSocket(endpoint, options)
}

/* The dial function returns a neffos client, a new `Conn` instance.
First parameter is the endpoint, i.e ws://localhost:8080/echo,
the second parameter can be any object of the form of:
Expand Down Expand Up @@ -732,6 +714,14 @@ function makeWebsocketConnection(endpoint: string, options?: Options | any) {
See https://github.com/kataras/neffos.js/tree/master/_examples for more.
*/
function dial(endpoint: string, connHandler: any, options?: Options | any): Promise<Conn> {

return _dial(endpoint, connHandler, 0, options);
}

// this header key should match the server.ServeHTTP's.
const websocketReconnectHeaderKey = 'X-Websocket-Reconnect';

function _dial(endpoint: string, connHandler: any, tries: number, options?: Options | any): Promise<Conn> {
if (endpoint.indexOf("ws") == -1) {
endpoint = "ws://" + endpoint;
}
Expand All @@ -747,8 +737,31 @@ function dial(endpoint: string, connHandler: any, options?: Options | any): Prom
return;
}


if (isNull(options)) {
options = {};
} else if (isNull(options.headers)) {
options.headers = {};
}


// the reconnection feature is only for browser side clients only,
// nodejs and go side developers can implement their own strategies for now.
const reconnectEvery: number = (options.reconnect) ? options.reconnect : 0;

if (tries > 0 && reconnectEvery > 0) {
// options.headers = {
// [websocketReconnectHeaderKey]: tries.toString()
// };
options.headers[websocketReconnectHeaderKey] = tries.toString();
} else if (!isNull(options.headers[websocketReconnectHeaderKey])) /* against tricks */ {
delete options.headers[websocketReconnectHeaderKey];
}

const ws = makeWebsocketConnection(endpoint, options)
let conn = new Conn(ws, namespaces);
conn.reconnectTries = tries;

ws.binaryType = "arraybuffer";
ws.onmessage = ((evt: MessageEvent) => {
let err = conn.handle(evt);
Expand Down Expand Up @@ -789,10 +802,6 @@ function dial(endpoint: string, connHandler: any, options?: Options | any): Prom
ws.onerror = undefined;
ws.onclose = undefined;

// the reconnection feature is only for browser side clients only,
// nodejs and go side developers can implement their own strategies for now.
const reconnectEvery: number = (!isNull(options) && options.reconnect) ? options.reconnect : 0;

if (!isBrowser || reconnectEvery <= 0) {
conn.close();
return null;
Expand All @@ -812,8 +821,8 @@ function dial(endpoint: string, connHandler: any, options?: Options | any): Prom

conn.close();

whenResourceOnline(endpoint, reconnectEvery, () => {
dial(endpoint, connHandler, options).then((newConn: Conn) => {
whenResourceOnline(endpoint, reconnectEvery, (tries: number) => {
_dial(endpoint, connHandler, tries, options).then((newConn: Conn) => {
if (isNull(resolve) || resolve.toString() == "function () { [native code] }") {
// Idea behind the below:
// If the original promise was in try-catch statement instead of .then and .catch callbacks
Expand Down Expand Up @@ -848,8 +857,25 @@ function dial(endpoint: string, connHandler: any, options?: Options | any): Prom
});
}

function makeWebsocketConnection(endpoint: string, options?: Options | any) {
if (isBrowser) {
if (!isNull(options)) {
if (options.headers) {
endpoint = parseHeadersAsURLParameters(options.headers, endpoint);
}

function whenResourceOnline(endpoint: string, checkEvery: number, notifyOnline: () => void) {
if (options.protocols) {
return new WebSocket(endpoint, options.protocols);
} else {
return new WebSocket(endpoint)
}
}
}

return new WebSocket(endpoint, options)
}

function whenResourceOnline(endpoint: string, checkEvery: number, notifyOnline: (tries: number) => void) {
// Don't fire webscoket requests just yet.
// We check if the HTTP endpoint is alive with a simple fetch, if it is alive then we notify the caller
// to proceed with a websocket request. That way we can notify the server-side how many times
Expand All @@ -866,22 +892,17 @@ function whenResourceOnline(endpoint: string, checkEvery: number, notifyOnline:
// counts and sends as header the previous failures (if any) and the succeed last one.
let tries = 1;

let getFetchOptions = (): any => {
return {
method: 'GET',
headers: {
// this header key should match the server.ServeHTTP's.
'X-Websocket-Reconnect': tries.toString()
}
};
};
const fetchOptions = { method: 'HEAD' };

let reconnect = (): void => {
// Note:
// We do not fire a try immediately after the disconnection as most developers will expect.
fetch(endpointHTTP, getFetchOptions()).then(() => {
notifyOnline();
fetch(endpointHTTP, fetchOptions).then(() => {
notifyOnline(tries);
}).catch(() => { // on network failures.
// if (err !== undefined && err.toString() !== "TypeError: Failed to fetch") {
// console.log(err);
// }
tries++;
setTimeout(() => {
reconnect();
Expand All @@ -903,6 +924,9 @@ const ErrWrite = new Error("write closed");
Each `NSConn` can join to multiple rooms. */
class Conn {
private conn: WebSocket;
/* If > 0 then this connection is the result of a reconnection,
see `wasReconnected()` too. */
reconnectTries: number;

private _isAcknowledged: boolean;
private allowNativeMessages: boolean;
Expand All @@ -921,6 +945,8 @@ class Conn {

constructor(conn: WebSocket, namespaces: Namespaces) {
this.conn = conn;
this.reconnectTries = 0;

this._isAcknowledged = false;
this.namespaces = namespaces
let hasEmptyNS = namespaces.has("");
Expand All @@ -937,6 +963,12 @@ class Conn {
// });
}

/* The wasReconnected method reports whether the current connection is the result of a reconnection.
To get the numbers of total retries see the `reconnectTries` field. */
wasReconnected(): boolean {
return this.reconnectTries > 0;
}

isAcknowledged(): boolean {
return this._isAcknowledged;
}
Expand Down
Loading

0 comments on commit 91eb944

Please sign in to comment.