'onDisconnect prevents connection from auto closing even if cancelled
Documentation states "On Android, Firebase automatically manages connection state to reduce bandwidth and battery usage. When a client has no active listeners, no pending write or onDisconnect operations..., Firebase closes the connection after 60 seconds of inactivity."
I am assuming that once I do a cancel on onDisconnect, it should not require to keep the connection alive.
However once I use onDisconnect, even if I cancel it later, the connection never closes.
Without onDisconnect, the connection closes in about 1 min, as expected.
Just to narrow down the issue I made following snippet :
DatabaseReference someDbRef = FirebaseDatabase.getInstance().getReference("somePath") ;
someDbRef.setValue("noProblemTillHere"); // if I return immediately after this line, connection closes after ~ 1 minute
OnDisconnect onDisconnectRef = someDbRef.onDisconnect();
onDisconnectRef.setValue("abraKaDabra");
onDisconnectRef.cancel();// After this the connection is never closed. it keeps sending keepalive
Not sure what am I missing here - don't think I need to manage the underlying websocket or persistent connection myself
Logs : OnDisconnect reference created and cancelled. Connection never closes
2022-03-28 20:19:21.589 7486-7535/com.sw... D/RepoOperation: set: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1
2022-03-28 20:19:21.589 7486-7535/com.sw... D/DataOperation: set: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1 noProblemTillHere
2022-03-28 20:19:21.591 7486-7535/com.sw... D/Connection: conn_0 - Sending data: {t=d, d={a=p, r=3, b={p=Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1, d=noProblemTillHere}}}
2022-03-28 20:19:21.592 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 40005
2022-03-28 20:19:21.597 7486-7535/com.sw... D/RepoOperation: Aborting transactions for path: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1. Affected: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1
2022-03-28 20:19:21.598 7486-7535/com.sw... D/Connection: conn_0 - Sending data: {t=d, d={a=o, r=4, b={p=Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1, d=abraKaDabra}}}
2022-03-28 20:19:21.598 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 44994
2022-03-28 20:19:21.599 7486-7535/com.sw... D/Connection: conn_0 - Sending data: {t=d, d={a=oc, r=5, b={p=Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1, d=null}}}
2022-03-28 20:19:21.599 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 44998
2022-03-28 20:19:21.653 7486-7595/com.sw... D/WebSocket: ws_0 - ws message: {"t":"d","d":{"r":3,"b":{"s":"ok","d":""}}}
2022-03-28 20:19:21.654 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 44945
2022-03-28 20:19:21.654 7486-7535/com.sw... D/WebSocket: ws_0 - HandleNewFrameCount: 1
2022-03-28 20:19:21.655 7486-7535/com.sw... D/WebSocket: ws_0 - handleIncomingFrame complete frame: {t=d, d={r=3, b={d=, s=ok}}}
2022-03-28 20:19:21.655 7486-7535/com.sw... D/Connection: conn_0 - received data message: {r=3, b={d=, s=ok}}
2022-03-28 20:19:21.655 7486-7535/com.sw... D/PersistentConnection: pc_0 - p response: {d=, s=ok}
2022-03-28 20:19:21.665 7486-7595/com.sw... D/WebSocket: ws_0 - ws message: {"t":"d","d":{"r":4,"b":{"s":"ok","d":""}}}
2022-03-28 20:19:21.666 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 44988
2022-03-28 20:19:21.666 7486-7595/com.sw... D/WebSocket: ws_0 - ws message: {"t":"d","d":{"r":5,"b":{"s":"ok","d":""}}}
2022-03-28 20:19:21.666 7486-7535/com.sw... D/WebSocket: ws_0 - HandleNewFrameCount: 1
2022-03-28 20:19:21.667 7486-7535/com.sw... D/WebSocket: ws_0 - handleIncomingFrame complete frame: {t=d, d={r=4, b={d=, s=ok}}}
2022-03-28 20:19:21.667 7486-7535/com.sw... D/Connection: conn_0 - received data message: {r=4, b={d=, s=ok}}
2022-03-28 20:19:21.667 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 44999
2022-03-28 20:19:21.667 7486-7535/com.sw... D/WebSocket: ws_0 - HandleNewFrameCount: 1
2022-03-28 20:19:21.667 7486-7535/com.sw... D/WebSocket: ws_0 - handleIncomingFrame complete frame: {t=d, d={r=5, b={d=, s=ok}}}
2022-03-28 20:19:21.667 7486-7535/com.sw... D/Connection: conn_0 - received data message: {r=5, b={d=, s=ok}}
2022-03-28 20:20:06.668 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 0
2022-03-28 20:20:51.672 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: -3
2022-03-28 20:21:36.676 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: -2
2022-03-28 20:22:21.679 7486-7535/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: -2
if instead I use following code snippet then, the connection autocloses after about 1 min as expected.
DatabaseReference someDbRef = FirebaseDatabase.getInstance().getReference("somePath") ;
someDbRef.setValue("noProblemTillHere");
//OnDisconnect onDisconnectRef = someDbRef.onDisconnect();
//onDisconnectRef.setValue("abraKaDabra");
//onDisconnectRef.cancel();
Logs : Connection autocloses when OnDisconnect reference was not created. (As expected)
2022-03-28 20:16:28.169 7296-7350/com.sw... D/RepoOperation: set: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1
2022-03-28 20:16:28.170 7296-7350/com.sw... D/DataOperation: set: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1 noProblemTillHere
2022-03-28 20:16:28.175 7296-7350/com.sw... D/Connection: conn_0 - Sending data: {t=d, d={a=p, r=3, b={p=Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1, d=noProblemTillHere}}}
2022-03-28 20:16:28.176 7296-7350/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 37864
2022-03-28 20:16:28.197 7296-7350/com.sw... D/RepoOperation: Aborting transactions for path: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1. Affected: /Games/games/vRYkQQs5LpSCjDxzXMP1Qvmndog1
2022-03-28 20:16:28.262 7296-7409/com.sw... D/WebSocket: ws_0 - ws message: {"t":"d","d":{"r":3,"b":{"s":"ok","d":""}}}
2022-03-28 20:16:28.263 7296-7350/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: 44913
2022-03-28 20:16:28.263 7296-7350/com.sw... D/WebSocket: ws_0 - HandleNewFrameCount: 1
2022-03-28 20:16:28.264 7296-7350/com.sw... D/WebSocket: ws_0 - handleIncomingFrame complete frame: {t=d, d={r=3, b={d=, s=ok}}}
2022-03-28 20:16:28.265 7296-7350/com.sw... D/Connection: conn_0 - received data message: {r=3, b={d=, s=ok}}
2022-03-28 20:16:28.265 7296-7350/com.sw... D/PersistentConnection: pc_0 - p response: {d=, s=ok}
2022-03-28 20:17:13.265 7296-7350/com.sw... D/WebSocket: ws_0 - Reset keepAlive. Remaining: -1
2022-03-28 20:17:28.271 7296-7350/com.sw... D/PersistentConnection: pc_0 - Connection interrupted for: connection_idle
2022-03-28 20:17:28.273 7296-7350/com.sw... D/Connection: conn_0 - closing realtime connection
2022-03-28 20:17:28.273 7296-7350/com.sw... D/WebSocket: ws_0 - websocket is being closed
2022-03-28 20:17:28.275 7296-7350/com.sw... D/PersistentConnection: pc_0 - Got on disconnect due to OTHER
2022-03-28 20:17:28.329 7296-7350/com.sw... D/WebSocket: ws_0 - closed
EDIT Reproduced the issue in minimal code. https://gist.github.com/amjaingzb/9bd83653f96d4dcfbc7dab5c25558f59
Additionally there seems to be a race condition as well with goOffline() and goOnline() as mentioned in the gist above.
Solution 1:[1]
An onDisconnect handler is registered on the server, not on the client.
Cancelling the onDisconnect handler from the client, removes that registration from the server. Aside from restarting the inactivity timer, it does not change anything about the client's connection management.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Frank van Puffelen |
