Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis keyPrefix Problem #232

Closed
canozgen9 opened this issue May 24, 2019 · 20 comments
Closed

Redis keyPrefix Problem #232

canozgen9 opened this issue May 24, 2019 · 20 comments

Comments

@canozgen9
Copy link

canozgen9 commented May 24, 2019

  • Echo Version: 1.5.3
  • Laravel Version: 5.8.*
  • PHP Version: 7.2.17
  • NPM Version: 6.8.0
  • Node Version: 8.10.8

Description:

When Echo used with Redis, it produces keyPrefix to every channel you created. (which is by default "laravel_database_")

Steps To Reproduce:

1-) Use Redis as Broadcast Driver and Queue Connection

BROADCAST_DRIVER=redis
QUEUE_CONNECTION=redis

2-) Create any Event

class UserRegistered implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function broadcastOn()
    {
        return new PrivateChannel('test');
    }

    public function broadcastAs()
    {
        return 'user.registered';
    }

    public function broadcastWith()
    {
        return ['id' => $this->user->id];
    }
}

3-) Broadcast this event with Private Channel called 'test'
4-) Authorize this channel

Broadcast::channel('test', function ($user) {
    return $user;
});

5-) Initialize Echo in your js file

import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001',
    authEndpoint: "/broadcasting/auth",
});

6-) Initialize your channel

 Echo.private(`test`)
                .listen('.user.registered', function (e) {
                    console.log(e);
                });

7-) Send event

event(new UserRegistered($user));

8-) See laravel-echo-server logs

[6:13:51 AM] - W3drJJWfqL9OacTmAAAa authenticated for: private-test
[6:13:51 AM] - W3drJJWfqL9OacTmAAAa joined channel: private-test
Channel: foo_bar_database_private-test
Event: user.registered

My Redis keyPrefix is "foo_bar_database_", so the channel name that the event emitted is "foo_bar_database_private-test" but i am listening the channel "private-test". So Echo never gets the event.

I tried to delete "private-" prefixes from both php&js side but this time Echo not requiring to authenticate channel anymore since not see as private channel.

@canozgen9
Copy link
Author

It can be fixed by below steps.
1-) Remove all "'private-' + " prefixes in your compiled Echo.js
This will make your channel name not being prefixed with "private-".
2-) At the backend part, authorize your channels in routes/channels.php as follows
Add your prefix to channel name.

Broadcast::channel('foo_bar_database_private-test', function ($user) {
   return true;
});

3-) At the frontend part, register your channels as follows
Add your prefix to channel name. Your channel name will not be prefixed with "private-".

Echo.private(`foo_bar_database_private-test`)
                .listen('.user.registered',function (e) {
                    console.log(e);
                });

4-) Broadcast event and see console output for laravel-echo-server

[7:19:56 AM] - 5KykLGFS9kiYu8pFAAAF authenticated for: foo_bar_database_private-test
[7:19:56 AM] - 5KykLGFS9kiYu8pFAAAF joined channel: foo_bar_database_private-test
Channel: foo_bar_database_private-test
Event: user.registered

5-) As you can see, the channel names match.

To solve this bug, Private("private-") and Presence("presence-") prefixes should not be mandatory.

@driesvints
Copy link
Member

Do you actually need the Redis prefix in this situation?

@AdSegura
Copy link

Same problem here.

Echo.private will add a prefix private- to channel's name.

So Laravel adds laravel_database_private-channel prefix and

Echo.private(laravel_database_private-channel) will add another prefix like so:

private- laravel_database_private-channel

And Echo will not get the event never becouse it's listening on other channel.

@AdSegura
Copy link

I was able to get it working:

In config/database.php disable prefix for redis.

Now i can do

 window.Echo.private('channel')

And in routes/channels.php

Broadcast::channel('channel', function ($user) {

With redis-cli monitor 👍

1558979801.909666 [0 172.20.0.1:35198] "PUBLISH" **"private-channel"** "{\"event\":\"App\\\\Events\\\\PrivateMessage\",\"data\":{\"msg\":\"Hello\",\"user\":\"foo\",\"socket\":\"vDVEap6hCjgJ5OhtAAAB\"},\"socket\":\"vDVEap6hCjgJ5OhtAAAB\"}"

And Echo clients gets their message.

@canozgen9
Copy link
Author

Do you actually need the Redis prefix in this situation?

Actually i do, because i have a server with multiple websites. The keys may conflict.

@driesvints
Copy link
Member

driesvints commented May 28, 2019

We probably don't want to fiddle too much with the internals with Echo. Is there some way we can strip the redis prefix again when fetching the events? Trying to think out loud here.

@driesvints
Copy link
Member

Closing this since this is more of a framework issue than echo. Let's continue the discussion here: laravel/framework#28701

@thomaswardiii
Copy link

thomaswardiii commented Oct 21, 2019

I know this is closed but I disagree that this is a framework issue. The echo server should be configurable such that if there is a prefix it can be prepended to the names of the keys. If this is how Laravel writes to redis, why should this not support that prefix?

It tends to default to strtolower(Str::snake(config('app.name')))

@eightyfive
Copy link

This is definitely a laravel/echo issue IMHO. Backend behaves as expected: Sending namespaced events to the laravel-echo-server. It's up to the client to know what namespaced events it wants to listen to.

@eightyfive
Copy link

@driesvints

const echo = new Echo({
  // ...
  keyPrefix: "laravel_database_"
});

What do you think?

@driesvints
Copy link
Member

@eightyfive laravel echo server has introduced a prefix by now: laravel/framework#28701 (comment)

@eightyfive
Copy link

@driesvints Indeed and echo server does broadcast the event with the keyPrefix. So nothing wrong here.

Problem is echo Client no picking up that prefixed event: laravel_database_private-App...

I’m pretty sure I am not mistaken cause when I remove the keyPrefix everywhere (Laravel & echo server), echo client works fine. So it’s pretty clear it does not listen to the keyPrefixed event name.

Let me know, thanks.

@driesvints
Copy link
Member

@eightyfive can you verify with laravel-echo-server that this never worked on their side and report back? Thanks!

@niocncn
Copy link

niocncn commented Feb 2, 2020

same issue, keyPrefix in echo options needed =(

@eightyfive
Copy link

Hey all,

This has been fixed in laravel/framework.

Turns out the Redis Broadcaster was ignoring the database.redis.prefix config option.

My bad pointing out the problem might come from laravel-echo client.

@skeeith
Copy link

skeeith commented Feb 23, 2020

@eightyfive Laravel still has this issue BTW. I just created a fresh Laravel app and tested this. confirmed it is still broadcasting the database redis prefix

@skeeith
Copy link

skeeith commented Feb 23, 2020

@eightyfive I found the solution.

On your larave-echo-server.json file

"databaseConfig": {
	"redis": {
		"keyPrefix": "your_prefix_database_"
	},
}

On your js files

Echo.channel('your-channel-name').listen('YourEventName', (event) => {
    console.log(event);
});

@eightyfive
Copy link

Problem was caused by [6.x] Fix channel names when broadcasting via redis, not by databaseConfig.redis.keyPrefix which is well-documented.

@omarjebari
Copy link

As you're using Laravel just edit your .env file and set:

REDIS_PREFIX=

This will remove the 'foo_bar_database_' prefix from your channel names. Then make sure you've restarted your services.

@mengdodo
Copy link

REDIS_PREFIX can not be removed in my project

so

    public function broadcastOn()
    {
        return new PrivateChannel('doctor.qa.user_1');
    }
window.Echo.channel('nongji:private-doctor.qa.user_1')
    .listen('OrderMessage', e=>{
        console.log(e
    })

nongji is REDIS_PREFIX variable in my project 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants