Disconnect handler does not work when turning on airplane mode (iOS)

638 views
Skip to first unread message

ch...@getpulled.com

unread,
Feb 24, 2015, 11:14:50 AM2/24/15
to fireba...@googlegroups.com
So I'm building presence into my app by setting a flag in firebase called `isOnline` to true when the app becomes active and when I initialize the account. For the most part this works, the user is flagged as offline when I kill the app. But when I go into airplane mode, my disconnect handler is never called and the user still appears online. 

After reestablishing the connection, I do an action that writes to firebase, and on this write (could be anything at all), the `isOnline` flag is usually set to false. There were a couple occasions where it sets to false, then immediately to true. I'm a bit confused.

This is how I'm handling going online:

    - (void)goOnline
   
{
       
Firebase *connectedref = [[[Firebase alloc] initWithUrl:kPULFirebaseURL] childByAppendingPath:@".info/connected"];
       
[connectedref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
           
if ([snapshot.value boolValue])
           
{
               
Firebase *fire = [[[[[Firebase alloc] initWithUrl:kPULFirebaseURL] childByAppendingPath:@"users"] childByAppendingPath:[PULAccount currentUser].uid] childByAppendingPath:@"isOnline"];
               
[fire setValue:@(YES)];
               
               
[fire onDisconnectSetValue:@(NO)];
           
}
       
}];
   
}

I call this method in my app delegate whenever the app becomes active and on launch. I am writing data when the app is in the background, so it only disconnects from firebase when the app is terminated or when data is not written in the background for ten to twenty minutes. 

What might cause this odd behavior? And is it ok to be setting the disconnect handler when it might already exist? 

Michael Lehenbauer

unread,
Feb 24, 2015, 5:52:30 PM2/24/15
to fireba...@googlegroups.com
Hey Chris,

A couple notes:
  1. I think you should only call that goOnline function (and set up the .info/connected listener) once.  If you do it multiple times, then you'll have multiple listeners and so you'll end up setting your "isOnline" bit multiple times each time you get connected.  Generally you should only need to set up your .info/connected listener once, on app start.

  2. Confusingly, your client and the Firebase server may have different notions of whether you're connected or not.  If everything goes well, then your socket connection to the server will be disconnected cleanly and both the client and server will notice immediately and the server will run your "onDisconnect" actions and the client will raise your ".info/connected" handler.

    But it's entirely possible for the socket to die uncleanly and the client and/or the server doesn't notice immediately.  We have some "backup" behavior in the server where if it doesn't hear from the client within ~2 minutes, it'll assume the socket is dead and will automatically clean up the client and trigger its onDisconnect actions.

    The client on the other hand doesn't have this fallback and will actually wait for the socket to disconnect, which is at the mercy of iOS.  So if iOS isn't actually notifying us that the socket is dead when you go into airplane mode, that would explain why your ".info/connected" handler isn't getting run.  The client should notice eventually though (iOS will time out the socket at some point).

    So it sounds like in your case, the socket is dying uncleanly, the server notices in a timely matter, but the client doesn't.
I'll open a bug for us to look into #2 a bit more (we might be able to tweak some socket options so that we get notified sooner or something).  Let me know if this is blocking you.

Thanks!
-Michael

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/29223a60-20f0-47cc-9e1a-bf61b3db8458%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Greg Soltis

unread,
Feb 24, 2015, 5:53:45 PM2/24/15
to fireba...@googlegroups.com
Hi Chris,

In some cases, and airline mode in particular, the on disconnect handler can take a while to trigger. Specifically, if the client has outstanding event listeners that are relatively busy, Firebase may end up waiting for TCP timeout before running the on disconnect handler. In the worst case, this can be upwards of 30 minutes. We are currently investigating ways of bringing this delay down, so expect to see improvements in the future. 

In general, we aim for a grace period on the order of a couple minutes for connections that appear slow, which is how airplane mode manifests, before declaring the connection closed.

Hope that helps!

-Greg

On Tue, Feb 24, 2015 at 8:14 AM, <ch...@getpulled.com> wrote:

--
Reply all
Reply to author
Forward
0 new messages