kerimamansaryyev / dart_pusher_channels

MIT License
48 stars 13 forks source link

Client Trigger is not working #20

Closed LUK3D closed 1 year ago

LUK3D commented 1 year ago

Hello, thanks for this awesome package! I'm trying to trigger an event using ´myPrivateChannel.trigger´ method but it's not working.

The code to trigger:

Future sendNotification(String channel, Map<String, dynamic> data) async {
  myPrivateChannel.trigger(
    eventName: 'client-to_user',
    data: data,
  );
}

Listening to the events:

StreamSubscription somePrivateChannelEventSubs =
myPrivateChannel!.bind('private-to_user').listen((event) {
print('Notifications Event: $event');
});

StreamSubscription<ChannelReadEvent> allEventsSubs =
    myPrivateChannel!.bindToAll().listen((event) {
  print('Event from the private channel fired! $event');
});
kerimamansaryyev commented 1 year ago

Hello, @LUK3D , could you please send me a piece of code where exactly you call sendNotification.?Moreover, .trigger method is not of type Future<void>, it has type of void. So try:

void sendNotification(Map<String, dynamic> data) async {
  myPrivateChannel.trigger(
    eventName: 'client-to_user',
    data: data,
  );
}

Couple of things to keep in mind:

  1. Ensure that you are triggering event after you subscribed to a channel. Channels have states:
    
    StreamSubscription somePrivateChannelEventSubs =
    myPrivateChannel!.whenSubscriptionSucceeded().listen((event) {

/// Try using status setState((){ currentStatus = myPrivateChannel?.state?.status }); });

2. When sending `data` ensure that the values of the map have basic type, because it is being encoded before sent:
```dart
/// good
{
   'hello':'hello'
   'someInt':1, 
   'innerMap':{
       'hello':'hello',
   }
}
/// bad
{
  'hello':MyClass(),
}
kerimamansaryyev commented 1 year ago

@LUK3D , please keep the thread up-to-date, I will be here to help and we will sort the issue.

kerimamansaryyev commented 1 year ago

@LUK3D

So, I am back with some updates on the issue.

  1. This package does not provide a way when channels subscription is awaited. It was made intentionally for flexibility, to allow developers to implement their own use-cases. So there is one of them, when Completer of the channel's subscription is awaited before triggering the event.

    
    void main() async {
    PusherChannelsPackageLogger.enableLogs();
    
    Completer myPrivateChannelSubscriptionCompleter = Completer();
    
    void completeSafely() {
    if (!myPrivateChannelSubscriptionCompleter.isCompleted) {
      myPrivateChannelSubscriptionCompleter.complete();
    }
    }
    
    const testOptions = PusherChannelsOptions.fromCluster(
    scheme: 'wss',
    cluster: 'mt1',
    key: 'a0173cd5499b34d93109',
    port: 443,
    );
    final client = PusherChannelsClient.websocket(
    options: testOptions,
    connectionErrorHandler: (exception, trace, refresh) async {
      completeSafely();
      myPrivateChannelSubscriptionCompleter = Completer();
      refresh();
    },
    );
    
    final myPresenceChannel = client.presenceChannel(
    'presence-channel',
    authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate
        .forPresenceChannel(
      authorizationEndpoint: Uri.parse('https://test.pusher.com/pusher/auth'),
      headers: const {},
    ),
    );
    
    void connect() {
    client.connect();
    myPrivateChannelSubscriptionCompleter = Completer();
    }
    
    void triggerEvent() async {
    await myPrivateChannelSubscriptionCompleter.future;
    myPresenceChannel.trigger(
      eventName: 'client-event',
      data: {
        'hello': 'hello',
      },
    );
    }
    
    StreamSubscription<ChannelReadEvent> channelSubscriptionEventSubs =
      myPresenceChannel.whenSubscriptionSucceeded().listen((_) {
    completeSafely();
    });
    
    StreamSubscription connectionSubscription =
      client.onConnectionEstablished.listen((_) {
    myPresenceChannel.subscribeIfNotUnsubscribed();
    });
    
    connect();
    // And you can call it wherever you want
    triggerEvent();
    }
2. Open [test.pusher.com](https://test.pusher.com). Click to the button `Trigger(Client)`. And you will see the following logs on the web-site:

20:25:59 debug Pusher : : ["Event sent",{"event":"client-event","data":{"data":"hello client"},"channel":"presence-channel"}] 20:25:58 debug Pusher : : ["Event sent",{"event":"client-event","data":{"data":"hello client"},"channel":"presence-channel"}] 20:25:52 debug Pusher : : ["Event sent",{"event":"client-event","data":{"data":"hello client"},"channel":"presence-channel"}]

So my assumption is that - the client who **send** the client events are not supposed to receive them back from a server. Because above logs say `Event sent` but there is no `Event recd` for my user. However, I can get it from my 2nd browser window with the same website for my 2nd user:

20:30:18 debug Pusher : : ["No callbacks on presence-channel for client-event"] 20:30:18 debug Pusher : : ["Event recd",{"event":"client-event","channel":"presence-channel","data":{"data":"hello client"},"user_id":"463"}] 20:30:11 debug Pusher : : ["No callbacks on presence-channel for client-event"] 20:30:11 debug Pusher : : ["Event recd",{"event":"client-event","channel":"presence-channel","data":{"data":"hello client"},"user_id":"463"}] 20:30:03 debug Pusher : : ["No callbacks on presence-channel for client-event"] 20:30:03 debug Pusher : : ["Event recd",{"event":"client-event","channel":"presence-channel","data":{"data":"hello client"},"user_id":"463"}]



So, please:

1. Try triggering events on  [test.pusher.com](https://test.pusher.com) with 2 browser windows (representing 2 users) .
2. Review the code above when you wait until you subscribe to a channel.
3. I've tested the above code in console app (didn't have time to build the separate app on Flutter) but I hope you got the point with it. The code was tested using the options for   [test.pusher.com](https://test.pusher.com). So try triggering the client events with the code and monitor the logs from the test website. Make sure you have proper `cluster` and `key` from the website (you can also find them opening developer console from the website and find from the wss connection).
4. Check if your backend allows receiving own client events per user.
kerimamansaryyev commented 1 year ago

So briefly, the client event might be triggered but you can't see it from the perspective of the user WHO SENT the event. So I recommend you to check your backend's logs if they have the client event and review the previous comment.

kerimamansaryyev commented 1 year ago

@LUK3D , have you made any success on the issue?

muhamadirwan99 commented 1 year ago

Hi @kerimamansaryyev , how can i get data from event response like Received an event: {"event":"client-event","data":"{\"data\":\"hello client\"}","channel":"presence-channel","user_id":"141"}

kerimamansaryyev commented 1 year ago

Hi @kerimamansaryyev , how can i get data from event response like Received an event: {"event":"client-event","data":"{\"data\":\"hello client\"}","channel":"presence-channel","user_id":"141"}

  1. Subscribe to some channel https://pub.dev/packages/dart_pusher_channels#subscribing-unsubscribing-and-connecting
  2. Bind to the event by its name https://pub.dev/packages/dart_pusher_channels#binding-to-events
  3. Use data or rootObject property of the incoming event.
    /// Prints whole object of the event.
    print(event.rootObject);
    /// Prints the data property of the event. It has type of dynamic but in most of the cases it's encoded string.
    print(event.data);
muhamadirwan99 commented 1 year ago

thank you for your response, I have one question again. how can I listen to data with StreamBuilder()?

kerimamansaryyev commented 1 year ago

@muhamadirwan99

...
StreamBuilder<ChannelReadEvent>(
stream: myChannel.bind('name_of_your_event'),
...
kerimamansaryyev commented 1 year ago

@LUK3D , I am closing this issue because of inactivity, feel free to reopen it if the issue is not resolved by: this comment . Briefly: Seems that there is nothing wrong with the package, it does not miss features, users are simply unable to get events that were published by themselves. So check logs on your server-side, I am sure that you can see that you receive the client events from there.