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.