Boost logo

Boost :

From: Marcelo Zimbres Silva (mzimbres_at_[hidden])
Date: 2023-01-21 15:09:28


On Sat, 21 Jan 2023 at 15:01, Ruben Perez <rubenperez038_at_[hidden]> wrote:
>
> > > 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk