bjovanov
bjovanov

Reputation: 481

Laravel echo not receiving events

I am implementing real time in my mobile application with Laravel Echo and React Native. I followed the documentation but it doesn't work anyway.

I use the Redis driver to broadcast my events, Laravel-echo-server for the Socket.io server and Socket.io-client on the client side to listen to events.

Everything seems to work perfectly on the Redis side because via the "redis-cli monitor" command, the event is well written. On the Laravel-echo-server side, everything looks good too because I have this in my logs when I trigger the event (so I suppose that the user successfully joined the channel):

[2:54:48 PM] - Eri_5PZDB5gkvShrBBBH authenticated for: private-App.User.4016
[2:54:48 PM] - Eri_5PZDB5gkvShrBBBH joined channel: private-App.User.4016
Channel: ami_database_private-App.User.4016
Event: App\Events\UpdateRequest

Except that I don't have the event triggered on the client side and I have nothing in the Chrome development console. I also checked the "Network" tab in the "WS" section and likewise, nothing is displayed.

I have already tried all the solutions proposed on the different topics of the forum but it doesn't change anything

Here is how I define the channel in the event (and my class implement ShouldBroadcast):

public function broadcastOn()
{
    return new PrivateChannel('App.User.' . $this->receiver->id);
}

This is how I trigger the event: I'm using EC2 and Elasticache from AWS

event(new UpdateRequest($receiver));

// I also tried this one
broadcast(new UpdateRequest($receiver));

This is my configuration in laravel-echo-server.json file

{
    "authHost": "<MY_EC2_IP>:80",
    "authEndpoint": "/broadcasting/auth",
    "clients": [
        {
            "appId": "<appId>",
            "key": "<key_id>"
        }
    ],
    "database": "redis",
    "databaseConfig": {
        "redis": {
            "port": 6379,
            "host": "<MY_ELASTICACHE_REDIS_ENDPOINT>"
        },
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": true,
    "host": null,
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "secureOptions": 67108864,
    "sslCertPath": "",
    "sslKeyPath": "",
    "sslCertChainPath": "",
    "sslPassphrase": "",
    "subscribers": {
        "http": true,
        "redis": true
    },
    "apiOriginAllow": {
        "allowCors": false
    }
}

On the client side, here's how I use echo in my React Native application: (I define the host as the IP of my EC2 instance because I run Laravel-echo-server on it)

export const echo = new Echo({
      broadcaster: 'socket.io',
      host: `http://${MY_EC2_IP}:6001`,
      client: Socketio,
      auth: {
        headers: {
          Accept: 'application/json'
        }
      }
})

I call echo at the very beginning of my app. In this way, it is never unmount

echo.private('App.User.' + this.props.userId)
        .listen('UpdateRequest', function (e) {
          console.log('UpdateRequest', e)
        })

EDIT:


I forgot to show you the .env file:

BROADCAST_DRIVER=redis
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

I have already tried with the following commands:

php artisan queue:work
php artisan queue:listen

I also tried to define a name specific to my events, I changed ShouldBroadcast interface to ShouldBroadcastNow, I just spent 1 hour examining the source code of Laravel Echo and there is nothing to indicate that my way of doing things is wrong.

There is no error message, no exception, nothing.

Please, I need help because I'm out of ideas.

Regards !

Upvotes: 4

Views: 7408

Answers (2)

juslintek
juslintek

Reputation: 511

You can as well add this prefix as MIX_ environmental variable or add it to your pipeline envs on both frontend and backend projects and append it to channels or write wrapper function called, echoListen('channel-name') which returns echo instance.

 const echoPrivate = (channel) => {
  return new Echo({
...options
}).private(process.env.MIX_CHANNEL_PREFIX + channel); 
 };
 
  const echoChannel = (channel) => {
  return new Echo({
...options
}).channel(process.env.MIX_CHANNEL_PREFIX + channel); 
 };
 
 export {
  echoPrivate,
  echoChannel,
 };

Upvotes: 0

bjovanov
bjovanov

Reputation: 481

I found the solution to my problem!

In fact, I was just not looking properly at the logs issued by Laravel-echo-server.

[2:54:48 PM] - Eri_5PZDB5gkvShrBBBH authenticated for: private-App.User.4016
[2:54:48 PM] - Eri_5PZDB5gkvShrBBBH joined channel: private-App.User.4016
Channel: ami_database_private-App.User.4016
Event: App\Events\UpdateRequest

If you look closely, my user joined the channel private-App.User.4016 because this part is managed on the client side by Laravel Echo.

But if we look at two lines below, we see that when my event is triggered, it publishes on the channel ami_database_private-App.User.4016 because this part is managed by Laravel and by default adds a prefix to the Redis entries.

Simply go to the config/database.php file and edit the following code:

'redis' => [

        // ...

        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'predis'),
            'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_').'_database_',
        ],

        // ...

    ],

to

'redis' => [

        // ...

        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'predis'),
            'prefix' => '',
        ],

        // ...

    ],

In this way, Laravel does not prefix the name of the channel on which he publishes the event and everything goes back to normal!

Hope it helps !

Upvotes: 8

Related Questions