Open Brinfotech1407 opened 3 years ago
Hi! Thanks for reporting this issue!
So in general you are not able to persist state when you are offline. From the link you sent:
This custom state persists on a channel as long as the user stays subscribed to that channel.
Set and get state is not currently exposed in the SDK. If that is something that you require, then we will be happy to prioritize it. But in general, you don't have to use Presence State to achieve what you described in your ticket (apart from last time online).
Background state changes can be handled by Flutter and usage of our custom Presence Widget. You should be able to detect if background state changes natively in Flutter (or using a plugin) and then change online
flag in the widget.
@are thanks for the revert and we studied the presence widget, understand the main purpose is to inform server via announce heartbeat or leave.
Our next question is what should we use for receiving and updating online / offline state on all clients for this user. Along with the presence widget we see 3 other files on the repo, do we have to use a combination of them to send and receive presence updates? Is any documentation to explain the overall implementation?
Our implementation and issues we are facing:
We are already monitoring app state in flutter and able to detect if app is in start, resume, pause, stop as well as if subscription is happening in background isolate due to message received via FCM.
We are using hereNow for the active channel, user is currently looking at in UI and checking occupancy count with UUID to show online status of the other user, challenge is even when we subscribe with presence false and no heartbeat from background isolate after getting an FCM notification it starts showing user as online because occupancy increases based on subscription.
We are using hereNow with 100 seconds interval for detecting the channel occupancy , but it keeps showing the user online/offline until the next hereNow API call is made. So what is the most optimal interval between two here now call or can we use some other method to show the user online/offline as soon as other user is online/offline ?
@are , after some more testing and logging, we see inconsistencies in the way the client gets events on the presence channel from the server. Below are some examples:
1st problem receiving a join event after announcing leave, without any action from another device i.e. app is still in the background and no new message etc is sent or received.
*When Subscribed receive Join Event ***** I/flutter ( 8698): │ 20-10-2021 12:36:14.130 (+0:21:40.906694) I/flutter ( 8698): │ 💡 I/Foreground : presence:Listener PresenceAction.join Received From =>rfdSbV7Teihkrc8sxr7Vk4ddtsm1 => for channel: 81d4f935-6df7-4ea8-9f39-2d5c211b3864-pnpres Occupants=> 2
**Sending Heartbeat to private channels*** I/flutter ( 8698): │ 20-10-2021 12:36:43.395 (+0:22:10.171627) I/flutter ( 8698): │ 💡 I/Foreground : _sendHeartbeat: Private Channel => {81d4f935-6df7-4ea8-9f39-2d5c211b3864}
****Annoucing Leave *** I/flutter ( 8698): │ 20-10-2021 12:37:57.758 (+0:23:24.534480) I/flutter ( 8698): │ 💡 I/Foreground : announceLeave: Private Channel => {81d4f935-6df7-4ea8-9f39-2d5c211b3864}
*Received leave event *** I/flutter ( 8698): │ 20-10-2021 12:37:59.378 (+0:23:26.154840) I/flutter ( 8698): │ 💡 I/Foreground : presence:Listener PresenceAction.leave Received From =>rfdSbV7Teihkrc8sxr7Vk4ddtsm1 => for channel: 81d4f935-6df7-4ea8-9f39-2d5c211b3864-pnpres Occupants=> 1
** NOW THIS IS WHERE PROBLEM IS --> Received join event again without sending heartbeat or resubscribing **** I/flutter ( 8698): │ 20-10-2021 12:39:09.330 (+0:24:36.106714) I/flutter ( 8698): │ 💡 I/Foreground : presence:Listener PresenceAction.join Received From =>rfdSbV7Teihkrc8sxr7Vk4ddtsm1 => for channel: 81d4f935-6df7-4ea8-9f39-2d5c211b3864-pnpres Occupants=> 2
2nd problem receiving presence on all subscribed channels, despite specifying a channel set for presence subscription separately, as mentioned earlier our use case we need presence only for private (1 to 1) channels only hence we specify those channels in presence channel set.
PubNub Channels Subscribed by this client
{eB9yTXzsHAaIjFqcA6lnHKNDxDf2, 3a99c6a0-096b-46a7-a2f0-5502d024fb12, 448b2b11-10d2-45d1-8cae-091ca645ab0c}
Sending Heartbeat to only private channel.
I/flutter ( 4175): │ 20-10-2021 19:29:37.488 (+0:01:06.852999) I/flutter ( 4175): │ 💡 I/Foreground : _sendHeartbeat: Private Channel => {3a99c6a0-096b-46a7-a2f0-5502d024fb12}
Receiving join event for all channels
I/flutter (12088): │ 20-10-2021 20:35:00.060 (+0:00:10.890071) I/flutter (12088): │ 💡 I/Foreground : presence:Listener PresenceAction.join Received From =>eB9yTXzsHAaIjFqcA6lnHKNDxDf2 => for channel: 448b2b11-10d2-45d1-8cae-091ca645ab0c-pnpres Occupants=> 2
I/flutter (12088): │ 20-10-2021 20:35:00.311 (+0:00:11.141646) I/flutter (12088): │ 💡 I/Foreground : presence:Listener PresenceAction.join Received From =>eB9yTXzsHAaIjFqcA6lnHKNDxDf2 => for channel: 81d4f935-6df7-4ea8-9f39-2d5c211b3864-pnpres Occupants=> 2
3rd problem receiving timeout from same client within 30 seconds of receiving a join event (as per PubNub documentation timeout is 320 seconds after connection breaks with server), even though second client subscription is on and no action done on the client, because of this occupancy becomes 1
│ 20-10-2021 22:22:39.624 (+0:03:34.530803) │ 💡 I/Foreground : presence:Listener PresenceAction.join Received From =>saurabhk => for channel: 5e654de1-dbf2-4937-b0b7-0ba9e1c1378c-pnpres Occupants=> 2
│ 20-10-2021 22:23:08.985 (+0:04:03.891403) │ 💡 I/Foreground : presence:Listener PresenceAction.timeout Received From =>saurabhk => for channel: 5e654de1-dbf2-4937-b0b7-0ba9e1c1378c-pnpres Occupants=> 1
All these events make the tracking so inconsistent and confusing for us to figure out what exactly is going on.
@are have you seen our comments, waiting for your response.
@are we have updated to latest stable version 4.0.0 and still facing same issues , waiting for your response.
Hi, So I gave it a try to replicate the issues which is described here related to inconsistency in tracking occupancy. Can we have more log information specifically about widget/application lifecycle events. e.g. To track what event is happening before we receive timeout event. Because I am not seeing those problems while trying replicating it.
Also,
receiving a join event after announcing leave, without any action from another device
We may get join after announcing leave If the subscription is still active(on message arrival or on subscription interval it informs pubnub server about its existence).
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
annouceLeave() // annoucing leave event when we app puts in background
} else if (state == AppLifecycleState.resumed) {
// resubscribePubnub();
if ((_paused.difference(DateTime.now()).inMinutes).abs() >= 10) {
_onNetworkConnected(); // re-subscribing if background to foreground comes after 10 mins
} else {
_client?.reconnect(); // re-connecting if we come less than 10 minutes from background to foreground
}
notificationService!.cancelAllNotifications();
}
}
when we puts a app in background we are announcing a leave event without unsubscribe , because if unsubscribe pubnub then we don't receive message from pubnub that's why i am not unsubscribing.
So i think related to our use case we needs to have a set and get state which will do our job , rather than depending Join and leave event.
Hi @are. What status of this issue? I wanna migrate our Flutter app to this package, but we use setting presence state https://www.pubnub.com/docs/presence/presence-state#setting-presence-state. Should we expect that it will be implemented and published soon?
Hi @are I seen that new release 4.2.1 got included setState and getState Function for presence one question I have that without passing UUID of other client how can I know the state. in latest SDK version below method is mentioned but it doesn't contains any UUID as a parameter can you help here , thanks.
Future<GetUserStateResult> getState( {Keyset? keyset, String? using, Set<String> channels = const {}, Set<String> channelGroups = const {}})
Our use case is to show the other member of a private (1 to 1) chat online or show the time when he/she was last online. Also, we want to ensure when a user puts the app in background state changes to offline and when the app is in foreground it changes to online. Also if the connection is closed due to inactivity it should show the user as offline.
With ref to below link how can i set and get the presence state for uuid with Dart SDK?
https://www.pubnub.com/docs/chat/features/presence