Closed Adidi closed 3 years ago
So this is in general a problem with connections on mobile devices - PubNub SDK cannot really tell if it's used in a mobile app or on server side, so it detects if the network is down only when its request fail. And one drawback of long-poll that PubNub is using is that sometimes the connection breaks and the SDK is not aware of it until it times out after few minutes.
You (as a developer of an app) can help the SDK by providing the info necessary to handle reconnection while bringing the app from the background.
import 'package:pubnub/core.dart';
// Somewhere in the app...
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if (result == ConnectivityResult.none) {
pubnub.reconnect();
}
});
This will bind the events from the connectivity
package to the SDK and will let the SDK know that it may need to restart its long-poll requests. Also you can call this method each time you suspect that the app may have been suspended.
Please note that this approach requires you to use some RetryPolicy
(an example on how to use it is shown here).
Let me know if that fixes your problem.
But if compare the result to none: if (result == ConnectivityResult.none) {
it means connection is off and then pubnub should reconnect ?
And again this isnt answer my question because when the app got idle i still have internet connection - the only problem is pubnub somehow get diconnected and i dont have any inidcation to it.
How can i tell if pubnub is not working - not necessarily by event - lets say i have the event telling me my app is back from background - do i have some property on pubnub or function telling me it disconnected from my channgel group ? something like that:
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
if (pubnub.isConnected) { // <-- or something else ? maybe channgelGroup.isSubscribed...
// perform reconnection logic here
}
}
}
Btw - status events are not supported in dart ?
Because of how networking works it is not possible to know when the connection is on or off. This - in general - is one of the biggest misunderstandings on how internet works. You cannot really know if a connection is working or not until you actually get a response. So in a case of a long-poll request you cannot possibly know if the server dropped the connection or not. Let me emphasize that this is not only a PubNub thing, it is how HTTP works.
So when you have those long-poll requests (which means 1 request can last as long as 280 seconds - almost 5 minutes) and the socket is destroyed for some reason (like app going idle or network instability) PubNub CANNOT possibly detect this if the system doesn't recognize that and signal the Dart runtime.
But you as the developer of the app can know common circumstances that may result in the connection breaking up and preemptively signal PubNub that it may want to restart its connections. This is what the pubnub.reconnect()
method is for - if the network is correctly working and sockets are connected, they will be simply restarted and there will be no impact.
If the connection is broken tho, this will allow the SDK to catch that and find a recourse of action.
So in actuality - any time that you would want to check pubnub.isConnected
(which doesn't and cannot exist) you can just call pubnub.reconnect()
instead.
But its not just reconnect - its also collecting all my missed message and generally initialize all pubnub logic (like i do when the app launch) wow - this is very inconvenience - i know that on websocket u can tell when you are disconnect. I think this is really a big drawback for pubnub. So can u tell me how much time the connection supposed to stay alive approximately when the app (mobile!) go idle ?
WebSocket can tell you when you disconnect only because it is polling for the connection underneath, so its way more resource-intensive.
PubNub does not assume what are you using your subscriptions and messages for, so if retrieving missing messages is a part of the application that is relevant for you, you need to implement that on your own. But don't forget that this is not always what you may want, for example you may not care if you receive all messages from the geolocated device, you only care that you get the latest ones with the latest position.
Usually if you need to catch up on messages (as in chat application), you would fetch latest messages from history each time the view is accessed and subscribe to receive new ones in real time. If the phone locks its screen you would want to refetch latest messages and refresh the subscription - same when you detect that the network goes down. But this is logic related specifically to your case and the SDK needs to be flexible so it cannot assume that this is always what you want.
And to answer your question how much time the connection stays alive after app goes idle - no, we don't really know that. Different phones and different Android versions handle it differently so you would need to figure it out for yourself, but in general I would assume that as soon as it goes idle you need to fetch new state.
Yes - my app is indeed chat messages anyway thanks ! i will make the launch code in every connection lost i think this is the only solution but if may i - I think you PubNub needs to find some solution to it (its supposed to be very simple) after all - we are a paying customers... Thank you for all your help man - really good support
Of course we are always happy to expand the SDK and add new functionalities, also keep in mind that PubNub Dart SDK is considerably younger than other SDKs and is quite more streamlined, so we really appreciate the feedback and always try to improve!
Thank you for your patience and understanding!
@are I am sorry to open it again but there is something cruicial of what u say: Is there a way the connection will get lost while the app is active and the connection is on and i still won't get any event on this ? If this is the case then I am sorry to tell you pubnub is not good for my use case at all.
If the connection can be lost from whatever reason it will and i cant know about it its really a big problem in the library that makes it unusable for chat solution - Can u clear those stuff for me ?
If you have any doubts if PubNub is suitable for your use case you should consult with our Support Team.
This is coming from my point of view as an engineer: What I'm trying to say is that in most of cases when connection broken the Dart runtime will throw an error and this is handled 100% through our SDK. However, there are certain cases that prevent self-recovery process in the SDK for reasons that are outside of our control. This is networking engineering issue that we cannot fix in our SDK because its how the internet works. If for example the connection is unstable and you get 100% packet loss, the SDK will take some time to realize that because the only mechanism to recover from 100% packet loss is timeout heuristics. So if the only thing that your application is using PubNub for is a subscription, then it's just not possible to prevent that from happening. But the SDK is trying to be as smart as possible, so if other requests (like publish or signal or history) fail, the subscribe loop will be restarted just in case.
Just to reiterate it further, because of how internet works it is not actually possible to know 100% in realtime if you are "connected" to the internet or not. All network activity that uses TCP is limited to that. To know that you can connect to server you actually need to make a request and receive a response, but this is limited to the point in time where you receive a response. After you receive the response you have no idea if you are still "connected" to the server or not so you need to make a request again.
We have many customers who use PubNub for their chat and it's working for them perfectly and reliably, so I don't think this is an issue with PubNub, but maybe with Dart SDK or the application architecture.
Im talking about issue with dart sdk again: I have the ability to know if the internet connection goes down:
@override // this is event by flutter mechanism
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
}
}
I am asking on a situation when there is an internet connection ! but my pubnub instance disconnected from their channels subscription (like it happaned when the phone got idle for some time)
So I am asking on that: if there is connection to internet and the phone is not idle - its active - is there still an option for pubnub instance subscription (to channel or channelgroup) to get lost ??
Think of a chat use case - i want to be able to listen always to every message ! and if the app goes idle - i can deal with it myself when it goes back again (through flutter event i have shown above) but if the stream connection to pubnub (channgel subscription) is getting lost while i am on the app and i dont have any inidcation on it - well - this is a really big problem since my user won't get messages that someone else sending to him and i(the developer) cant refresh his phone cause i dont know he got disconnected from pubnub
In the case that you described: no, it should not be possible. If internet connection is stable and the phone is not idle, then the subscription would not get lost. If it does, its probably a bug that you should report separately.
Ok - thanks !
How can we listen to status events in pubnub dart ? like in the docs. To my general question: Pubnub is unsubscribe from channels automatically when the phone goes idle (the app is still running but in the background) - How can get event for that - client is no more subscribing so i can handle it when the phone goes back from background myself.
register to the events:
pubnub.signals.networkIsConnected
is not working - i try to print something on this event and disconnect from my phone wifi - packageconnectivity
of dart is working - i get notify on it - but from pubnub listener i won't get this message