Test if socket is still open - javascript

Following instruction from my previous question, I now have an array of connected users in socket.io. My problem (which I was warned of in the answer) is that sockets stay in this array even after the browser has disconnected.
I tried removing sockets from the array in a socket.on('disconnect' function, but there is still a delay of ~1 minute between when the browser disconnects and socket.io triggers the disconnect.
What is the best way to "test" a socket to see if its actually alive? I am tempted to try to send a message and catch any errors, but I feel like there is a more elegant solution.

Solution on how to test if "socket is still open"
if(socket.readyState === socket.OPEN)
{
}
Why it works:
readyState = The current state of the connection; this is one of the Ready state
constants. Read only.
"the Ready state constants"
CONNECTING 0: The connection is not yet open.
OPEN 1: The connection is open and ready to communicate.
CLOSING 2: The connection is in theprocess of closing.
CLOSED 3: The connection is closed or couldn't be opened.
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket

I had an error in my disconnect handler. What I ended up using:
socket.on('disconnect', function() {
users.splice(users.indexOf(socket), 1);
});

socket.on('end',function(){
//your code
})
or
socket.on('error',function(err){
//in case of any errors
})
The disconnect event wont fire until all the clients has been disconnected!

Related

Using indexeddb operation in multiple tabs

I am trying to save data from one tab to indexeddb and trying to get the data from another tab. But the operation is happening in second tab, only when i close the first tab or close the indexeddb in first tab using indexeddb.close();
How to get the data from indexeddb from other tabs(without closing the first tab or the indexeddb instance in the first tab)?
Data stored in indexedDB is available to all tabs from within the same origin. First clarify that both tabs point to the same origin.
However, indexedDB locks access to its data to essentially one tab at a time. If you have a connection to an indexedDB database open in one tab, and attempt to open a connection to the same database in a second tab, the second connection stalls, because it is blocked by the open connection in the other tab.
Notice that I say stalls, not fails. This is because the connection will eventually succeed (it becomes unblocked) once the tab that has the open connection either closes the connection or when the version change transaction completes (the onupgradeneeded handler function completes). The success event for the attempt to open the connection will eventually fire once it is unblocked.
The connection can be closed by calling IDBDatabase.prototype.close on the open connection, or by simply closing the tab.
One way to avoid some of the unwanted behavior and minimize how often a blocked event occurs is to avoid using a global database connection. By global I mean a database connection that you open some time near the time the tab is opened, when the dom is loaded and such, and then leave open for the remainder of the lifetime of the tab. Instead of opening a connection once for the entire lifetime of the tab, open a connection only when you need it, and then close it thereafter, and reopen a connection each additional time you need it, and close it thereafter. This way, the connection is closed for the majority of the time the tab is open, instead of being open for the majority of the time.
With all of that pretext, the answer to your question then is:
In first tab, open a connection, write data, then close connection.
Without closing first tab, then in second tab, open a connection, read data, then close connection.
Pay attention to the 'blocked' event. Add a listener in tab2 that listens for it. If you witness this event, then you tried to connect in tab2 while the tab1 connection was still open. Change your application to be able to react to this situation.
Here is simplistic example of listening for a blocked event:
function open(name, version, callback) {
var request = indexedDB.open(name, version);
request.onsuccess = function(event) {
var db = request.result;
callback(result, null);
};
request.onerror = function(event) {
console.log('Failed to connect');
callback(null, 'error');
};
request.onblocked = function(event) {
console.log('Failed to connect because blocked');
callback(null, 'blocked');
};
}
open('foo', 1, function onopen(db, error) {
if(error === 'error') {
console.log('cannot do stuff because of error');
} else if(error === 'blocked') {
console.log('cannot do stuff because blocked');
} else {
console.log('do stuff with db', db.name);
// do db operation here
// cleanup when done
db.close();
}
});

PouchDB detect documents that aren't synced

I am trying to sync a local PouchDB instance to a remote CouchDB. Things work great, but I am not sure how to deal with the following situation:
I have added a validation rule in CouchDB to prevent updating (it will deny all updates). When I run the sync function on my local PouchDB instance after modifying a document, the "denied" event fires as I would expect. However, if I run sync a second time, the "denied" event doesn't fire again, even though the local document differs from the CouchDB version.
How can I check if the local database matches the remote database? If I miss the "denied" event the first time (lets say the user closes the browser), how can I detect on the next run that the databases are not in sync? How can I force PouchDB to try and sync the modified document again so that I can see the denied event?
Thanks!
syncPouch: function(){
var opts = {};
var sync = PouchDB.sync('orders', db.remoteDB, opts);
sync.on('change', function (info) {});
sync.on('paused', function(){
});
sync.on('active', function () {});
sync.on('denied', function(err){
//This only fire once no matter how many times I call syncPouch
console.log("Denied!!!!!!!!!!!!");
debugger;
});
sync.on('complete', function (info) {
//This fires every time
console.log("complete");console.log(info);
});
sync.on('error', function(err){
debugger;
});
return sync;
},
What I have noticed with validate_doc_update functions is that PouchDb appears to treat any "denied" document as sync-ed. So even if you then remove the validate_doc_update function, the document will not sync into the remote database on future attempts even though it is not the same.
So you can be left with an "out of sync" situation that can only be fixed by editing one of the documents again.
Perhaps you are seeing the same thing? Perhaps the "denied" event does not fire because there is no attempt by PouchDb to sync the document (as it has already attempted to sync it previously)?

SignalR Stops Working After A While

For some reason, SignalR will just stop calling client methods after a short period of time (about 1 hour or less I estimate). I have a page that shows Alerts... a very simple implementation. Here's the Javascript:
$(function () {
// enable logging for debugging
$.connection.hub.logging = true;
// Declare a proxy to reference the hub.
var hub = $.connection.alertHub;
hub.client.addAlert = function (id, title, url, dateTime) {
console.log(title);
};
$.connection.hub.start().done(function () {
console.log("Alert Ready");
});
});
If I refresh the page, it works again for about an hour, then will stop calling the client event addAlert. There are no errors in the log, no warnings. The last event in log (other than the pings to the server) is:
[15:18:58 GMT-0600 (CST)] SignalR: Triggering client hub event
'addAlert' on hub 'AlertHub'.
Many of these events will come in for a short while, then just stop, even though the server should still be sending them.
I am using Firefox 35.0.1 on Mac and SignalR 2.0.0.
I realize that a work-around is to force a page refresh every 10 mins or so, but I'm looking for a way to fix the root cause of the problem.
I enabled SignalR tracing on the server. I created an "alert" on the server after a fresh refresh of the Alert page and the alert came through. I waited about 10 mins and I tried it again, and it failed to come through. Here's what the logs read (sorry for the verbosity, not sure what was relevant):
SignalR.Transports.TransportHeartBeat Information: 0 : Connection b8b21c4c-22b4-4686-9098-cb72c904d4c9 is New.
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(b8b21c4c-22b4-4686-9098-cb72c904d4c9)
There are dozens more of the SignalR.Transports.TransportHeartBeat messages, but nothing else.
i think theres a timeout of default 110 seconds for signalr. Can you try signalr disconnected event to reconnect it back.
$.connection.hub.disconnected(function () {
setTimeout(function () {
startHub();
}, 5000);
});
and in startHub() you can start connection again.
reference : https://github.com/SignalR/SignalR/issues/3128
and How to use SignalR events to keep connection alive in the right way?
As it turns out the problem was the way I was handling the AlertHub connections. I am using Enterprise Library Caching to store connections backing the AlertHub, and I was expiring the cache entries 20 minutes after they were created. Ergo, when the server called the client method, no errors where reported because there were no client(s) to send the message(s) to.
I have since increased the cache expiration to a reasonable value, which solved the problem.
You can refresh page if client is inactive, no mouse movement (in about every 15-30 min). I had same problem and solved it that way. That was nasty workaround but later i forgot about it and never fixed it completly ;)

indexedDB.deleteDatabase() throws error

I am trying to delete a database for unit testing:
var DeleteDb = indexedDB.deleteDatabase(dbName);
this piece of code gets directly called in the first beforeEach in jasmine.
with chrome devTools i can see that DeleteDb.error has the following value:
error: [Exception: DOMException: Failed to read the 'error' property from 'IDBRequest': The request has not finished.]
DeleteDb.onsuccess or DeleteDb.onerror are never fired. Also i am never trying to read an 'error' property in the code.
Does somebody know what this error means, where it is coming from or how i can solve it?
UPDATE:
This code still sometimes fails for me. it gives me the same error as above.
<html>
<head>
<script>
var deleteDb = window.indexedDB.deleteDatabase('fakeNonExistentDatabase');
deleteDb.onsuccess = function() {
console.log('complete');
};
</script>
</head>
</html>
I am still not sure why this is happening. sometimes opening a new tab or closing another one works.
Also it never gives an error when removing the onsuccess callback
UPDATE 2
Well it seems that the code is actualy working, but the onsuccess event is never getting fired because no events are getting fired anymore when pressing F8 in chrome devtools. The error i;m getting now is:
Uncaught InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.
I thought the above error message was a result of the first error message in this post but actualy it was the other way around. There are a few pages i can find about this topic on the internet but there isn't really provided a answer.
Any thoughts?
Also check onblocked. There might be another db connection that keeps your delete request from neither succeeding nor failing.
It is possible to avoid this behaviour by listening to onversionchange on your opened connections and make sure to close the connection when that event is triggered.
Okay as it turns out all of my code was good but deleting a database a second time takes somwhere between 10 seconds and several minutes.
you can test this for yourself: the code in this post shows it
what was happening is that jasmine times out after 5 seconds by default (i changed this to a higher number but who would think i takes THAT long)
browser: Chrome 39.0.2171.71 m
Make sure when deleting
the RESULT from DB creation is not empty
close the RESULT before deleting
delete through the same connection you created
var init=function(){
var request = this.connection.open(name,version);
request.onupgradeneeded=function(e){
var version=e.target.result;
};
request.onsuccess=function(e){
db.result=e.target.result;
};
request.onerror=function(e){
};
};
var remove=function(){
if (typeof db.result !== 'undefined') {
db.result.close();
return this.connection.deleteDatabase(version);
}
}
This is 5 years late, but just in case there are more guys like me...
close the connection to the database before deleting it...

How configure reconnecting in socket.io?

I create socket.io connection with next code
var socket = new io.connect('http://localhost:8181', {
'reconnect': true,
'reconnection delay': 500,
'max reconnection attempts': 50
});
But when I kill server CTRL+C and start it again, reconnection isn't happening. But disconnect event raised on client side. What maybe reason of it?
This is an old question, but for other people like me, who are looking how to configure reconnect in socket.io (1.x) here is a correct syntax:
var socket = new io.connect('http://localhost:8181', {
'reconnection': true,
'reconnectionDelay': 1000,
'reconnectionDelayMax' : 5000,
'reconnectionAttempts': 5
});
I realise this is an old question, but I've been having some trouble with socket io reconnecting and found this post high in the search results, so thought I would contribue. Try debugging exactly which events are firing using the following code:
# coffeescript. compile if you're writing javascript, obviously.
socket.on 'connect',-> console.log 'connected'
socket.on 'reconnect',-> console.log 'reconnect'
socket.on 'connecting',-> console.log 'connecting'
socket.on 'reconnecting',-> console.log 'reconnecting'
socket.on 'connect_failed',-> console.log 'connect failed'
socket.on 'reconnect_failed',-> console.log 'reconnect failed'
socket.on 'close',-> console.log 'close'
socket.on 'disconnect',-> console.log 'disconnect'
This should give you more insight into the state of the client socket.
Also, try looking in the Network tab of your web inspector to see if it is firing XHR requests as a fallback. Finally, in your web console, try typing io.sockets and expand it out to see whether it is actually trying to reconnect or not.
I have encountered problems with reconnect_failed not firing, and the reconnect tally not resetting. The following are links to discussions of these issues on github.
reconnection delay - exponential back off not resetting properly
reconnect_failed gets never fired
some potential fixes/workarounds
This is an old question, but I had the same question (for a different reason) when using v1.4.5. My chat room app worked beautifully, but when I hit Ctrl+C in the terminal, my browser continued to loop and report ERR_CONNECTION_REFUSED every few seconds until I shut it down.
Changing a previous answer just a bit gave me the solution.
For v1.4.5, here is my original code for "var socket" in my client js file:
var socket = io();
And here is the solution:
var socket = io({
'reconnection': true,
'reconnectionDelay': 1000,
'reconnectionDelayMax' : 5000,
'reconnectionAttempts': 5
});
Obviously I could change the values if I want, but the important point is that this killed the never ending reconnection requests.
reconnection delay is too small 500ms increase that, on top of that 50 retries means 500 * 50 = 25000 ms which is 25 seconds. If that doesn't help set a timeout on error event on client side to recreate the socket object (After error and some delay retry to create connection).

Categories

Resources