redis / hiredis

Minimalistic C client for Redis >= 1.2
BSD 3-Clause "New" or "Revised" License
6.25k stars 1.82k forks source link

async: callback lifecycle management #925

Open tudor opened 3 years ago

tudor commented 3 years ago

I'm trying to wrap hiredis (in async mode) from C++, and I'd like the callbacks to have associated state that is freed when no longer needed.

For non-pub/sub callbacks, this is easy. Hiredis will call each callback exactly once (when the reply is received, or when the connection is lost).

For pub/sub callbacks, this is not so easy. The pub/sub callback can be called zero times (if I subscribe to the same channel a second time, the old callback is not called any more), or an unbounded number of times (once for the initial "subscribe" / "psubscribe", once for each message, once for the final "unsusbcribe" / "punsubscribe").

Also, because I'm trying to wrap hiredis in a relatively transparent way, I don't even know whether a command is pub/sub or not, and I'd rather not replicate the parsing logic.

RFC: I'd like to add a second callback mode in which callbacks are always called at least once, and the last call is done with a NULL reply, which I could use to free the associated state.

Non-pub/sub callbacks would be called twice during normal operation: once with the actual reply, once with NULL (or just once with NULL if the context is being freed).

Pub/sub callbacks would be called at least once: if replacing a callback, the old one is called with NULL. Otherwise, the callback is called N times (once for "subscribe", once per message, once for "unsubscribe") and then again with NULL at the last unsubscribe.

I'd be happy to send a PR, let me know if you think this idea has merit.

tudor commented 3 years ago

Alternatively (and possibly cleaner), I could associate a finalizer which is always called when a specific callback is no longer going to be called.