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

createAdapter(pubClient, subClient) breaks subClient.connect(): "Error: Cannot send commands in PubSub mode" #436

Closed
akifd opened this issue Dec 14, 2021 · 5 comments

Comments

@akifd
Copy link

akifd commented Dec 14, 2021

package.json

    "@socket.io/redis-adapter": "7.1.0",
    "redis": "4.0.1",
    "socket.io": "4.4.0"

The Redis itself is running in Docker with the image redis:6.2.6-alpine3.15.

Here is the code that doesn't work for some reason:

import { Server } from 'socket.io'
import { createClient } from 'redis'
import { createAdapter } from '@socket.io/redis-adapter'

const io = new Server()
const pubClient = createClient({url: `redis://redis:6379/1`})
const subClient = pubClient.duplicate()

io.adapter(createAdapter(pubClient, subClient))

Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
  io.listen(9003)
  console.log('Listening on port 9003...')

  async function redisTest() {
    await subClient.subscribe('channel', (message) => {
      console.log('Received message', message)
    })
    await pubClient.publish('channel', 'Hello')
    await pubClient.publish('channel', 'World!')
  }
  redisTest()
})

The code gives me the following error:

/code/node_modules/@node-redis/client/dist/lib/client/commands-queue.js:68
            return Promise.reject(new Error('Cannot send commands in PubSub mode'));
                                  ^

Error: Cannot send commands in PubSub mode
    at RedisCommandsQueue.addCommand (/code/node_modules/@node-redis/client/dist/lib/client/commands-queue.js:68:35)
    at RedisSocket.socketInitiator (/code/node_modules/@node-redis/client/dist/lib/client/index.js:304:81)
    at RedisSocket._RedisSocket_connect (/code/node_modules/@node-redis/client/dist/lib/client/socket.js:122:77)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Commander.connect (/code/node_modules/@node-redis/client/dist/lib/client/index.js:156:9)
    at async Promise.all (index 1)

If I remove the line io.adapter(createAdapter(pubClient, subClient)), it starts working again:

Listening on port 9003...
Received message Hello
Received message World!

If I remove the subClient.connect(), but leave the adapter, it doesn't crash, but I obviously won't receive the published messages:

Listening on port 9003...

Do I just need to downgrade some packages or why might I have this problem? It feels like the README is using outdated packages, as an example, the Redis createClient now takes the url option instead of the host and port mentioned in the README.

@akifd
Copy link
Author

akifd commented Dec 14, 2021

Hmm it seems to work if I move the io.adapter() after connecting the Redis clients:

import { Server } from 'socket.io'
import { createClient } from 'redis'
import { createAdapter } from '@socket.io/redis-adapter'

const io = new Server()
const pubClient = createClient({url: `redis://redis:6379/1`})
const subClient = pubClient.duplicate()

Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
  io.adapter(createAdapter(pubClient, subClient))
  io.listen(9003)
  console.log('Listening on port 9003...')

  async function redisTest() {
    await subClient.subscribe('channel', (message) => {
      console.log('Received message', message)
    })
    await pubClient.publish('channel', 'Hello')
    await pubClient.publish('channel', 'World!')
  }
  redisTest()
})

Is this intentional? If yes, the documentation should be updated to reflect this.

@darrachequesne
Copy link
Member

Hi! Unfortunately, I wasn't able to reproduce the issue. Could it be linked to redis/node-redis@ac808ea?

@LebonNic
Copy link

Hi! I got the same issue when deploying my app on a cloud provider. I had to move the io.adapter(createAdapter(pubClient, subClient)) part after the Promise.all([pubClient.connect(), subClient.connect()]) too.

darrachequesne added a commit that referenced this issue Jan 4, 2022
It seems the clients must be connected before creating the adapter.

Related: #436
@darrachequesne
Copy link
Member

OK, so I've updated the README and the documentation on the website: https://socket.io/docs/v4/redis-adapter/

Thanks for the heads-up!

@JoshBot-Debug
Copy link

JoshBot-Debug commented Feb 11, 2022

@darrachequesne You need to update this page as well, I was stuck here for ages lol. https://socket.io/docs/v4/server-api/#serveradaptervalue

const pubClient = createClient({
url: redis://${REDDIS_USER}:${REDDIS_PASSWORD}@${REDDIS_HOST}:${REDDIS_PORT},
})

And

// redis@4
Promise.all([pubClient.connect(), subClient.connect()])
.then(() =>
{
io.adapter(createAdapter(pubClient, subClient));
io.listen(PORT)
})

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

No branches or pull requests

4 participants