On Sat, 21 Jan 2023 at 15:01, Ruben Perez
Out of curiosity, does having the parsing done in async_exec (vs. in async_run) have to do with making no copies?
Yes, that is the main reason. It reduces latency.
I think I haven't explained myself - I've understood that doing the deserialization in async_run would require copying the data, while doing it in async_exec doesn't. Why?
Because that would require some form of type erasing. Each call to async_exec can have a different adapter co_await conn->async_exec(req, adapt(type1)); co_await conn->async_exec(req, adapt(type2)); // Elsewhere in the code co_await conn->async_exec(req, adapt(type3)); // ... ... To be able to read in async_run I would need those adapters, but that requires type-erasing to store them in the request queue. Even if I manage to do this cheaply, what would I gain? I don't think much.
[...] There is only one corner case where it is received as a push, the SUBSCRIBE command, because it does not have a response. When Redis sends the response I am not expecting any so I must treat it like a push although it has no resp3 push type.
From the discussion, I've got the impression that an application can send regular commands (e.g. SET, GET, and so on) while receiving server pushes (via SUBSCRIBE and async_receive). However, the official docs (https://redis.io/docs/manual/pubsub/) seem to disallow it ("A client subscribed to one or more channels should not issue commands") - it seems to make some exceptions to these, like ping, reset, unsubscribe and further subscribes. Is this true?
The docs are probably referring to the old protocol version RESP2. The new version RESP3 has a push type as you can see here https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md where you can find Push types are not related to replies, since they are information that the server may push at any time in the connection, so the client should keep reading if it is reading the reply of a command. Push data may be interleaved with any protocol data, but always at the top level, so the client will never find push data in the middle of a Map reply for instance. Note that in this mode it is possible to get both replies and push messages at the same time, interleaved in any way. This is how it becomes possible to implement client-side-caching using only one connection, see https://redis.io/docs/manual/client-side-caching/
b. Can you provide an example of the kind of mistake that would cause this to happen?
request req; req.push("SUBSCRIBE"); // oops, forgot to set a channel.
From the docs again, it seems like you always get a first message stating that you subscribed successfully to that channel, and the number of channels you're currently subscribed to. Would it be possible to parse that as a kind of "subscribe response"? It's currently being handled as a regular push.
The reply to the SUBSCRIBE command is a push type on the wire, so I can't distinguish it from other kinds of pushes and therefore I have to treat them the same. This is what a server push looks like on the wire btw ">4\r\n+pubsub\r\n+message\r\n+some-channel\r\n+some message\r\n" Regards, Marcelo