benashford / redis-async-rs

A Rust client for Redis, using Tokio
Apache License 2.0
253 stars 30 forks source link

Pub/Sub error: Unexpected("PUBSUB message should be encoded as an array") #88

Closed wildonion closed 1 year ago

wildonion commented 1 year ago

Hello, I tried to run the code provided in examples folder but for subscription I get this error, I don't know how to fix it. could you help me please.

i'm on MacOS M1 and using the redis-async = "0.16.0" also redis is hosted on docker

this is the code that I have currently

let mut stream_messages = redis_async_pubsubconn
                .subscribe(&topic)
                .await
                .unwrap();

and for receiving part

while let Some(message) = stream_messages.next().await{ 
      let resp_val = message.unwrap();
      let message = String::from_resp(resp_val).unwrap();
  }
benashford commented 1 year ago

Hmm, that is puzzling. I've tried the example in the examples folder and it works as expected. (Also MacOS, with Redis 7.0.12 running locally.)

The error message literally means that Redis is not providing messages in the expected format, which is each one is an array, as per the documentation: https://redis.io/docs/interact/pubsub/

Format of pushed messages

A message is an array-reply with three elements.

The first element is the kind of message:

subscribe: means that we successfully subscribed to the channel given as the second element in the reply. The third argument represents the number of channels we are currently subscribed to.

unsubscribe: means that we successfully unsubscribed from the channel given as second element in the reply. The third argument represents the number of channels we are currently subscribed to. When the last argument is zero, we are no longer subscribed to any channel, and the client can issue any kind of Redis command as we are outside the Pub/Sub state.

message: it is a message received as a result of a PUBLISH command issued by another client. The second element is the name of the originating channel, and the third argument is the actual message payload.

So we're not receiving a message in that format for some reason. I can only presume it's an incompatibility with the Redis version. This library has been tested with Redis 5 through to 7, and I don't think there's been any breaking changes with PUBSUB behaviour in Redis anyway.

It should be noted that this library doesn't support Redis clusters yet, so if you have a Redis cluster in Docker that might cause confusion, but I don't know if it would cause this particular problem.

wildonion commented 1 year ago

no actually there is no redis cluster in docker and I have latest reids container. I'm publishing message thourgh the redis cli also I have password set for the redis I don't see any where in the provided subscription example that the password is being used, is this the issue?

wildonion commented 1 year ago

I also put the subscription process inside an interval and didn't publish any message through the cli but still getting Unexpected("PUBSUB message should be encoded as an array")

benashford commented 1 year ago

That could well be it. If the Redis server needs a password, then we'll be receiving error messages from the Redis server that the library may not be parsing correctly hence that error message.

The examples assume a Redis server with no authentication, just to make the examples easier. If it does require a password then you can use the ConnectionBuilder instead. E.g.:

let mut builder = ConnectionBuilder::new(host, port);
builder.password(password);
let connection = builder.pubsub_connect().await?

That should work if there aren't any other problems elsewhere.

wildonion commented 1 year ago

ok nice, authentication was the actual issue now i'm receiving correctly I was stuck on this for a week, great thanks

benashford commented 1 year ago

The problem whereby the library is swallowing the authentication error was the main source of confusion. I'm making a small change here: https://github.com/benashford/redis-async-rs/pull/89 which would improve the error reporting when either an error value is received, or an unexpected value. Which should reduce confusion in this area, hopefully.