Discussion required: remove PreserveAsyncOrder by mgravell · Pull Request #877 · StackExchange/StackExchange.Redis (original) (raw)
@NickCraver OK, I had an idea. Let me rubber-duck this against you a sec.
consider: we add two methods onto ChannelMessageQueue:
public void OnMessage(Action<RedisChannel, RedisValue> handler) {...} public void OnMessage(Func<RedisChannel, RedisValue, Task> handler) {...}
These would only work once - if you try to OnMessage a second time it laughs at you. Implementation: exactly as shown above:
while (!queue.IsCompleted) { ChannelMessage next; try { next = await queue.ReadAsync(); } catch (ChannelClosedException) { break; } // an inbuilt
try { handler(next.Channel, next.Value); }
catch (Exception anythingElse) { ...log?...}}
(we'd probably kick off the initial exec on the TP, since Channel<T> loves TP)
and for the async case:
try { await handler(next.Channel, next.Value) ?? Task.CompletedTask; }Another more ambitious option:
I think that now that the machinery is in place, I could actually use this to reinstate PreserveAsyncOrder, but with a slightly different meaning:
- it would only apply on pub/sub
- it would only apply inside each individual subscription
We could also consider whether it makes sense to request this mode on a per-subscription basis (presumably via CommandFlags), but that's separate.
Basically, the idea is: if PreserveAsyncOrder is enabled (whether globally or per-subscription, implementation detail), we spin up a ChannelMessageQueue without showing the user, and call OnMessage with their handler.
This would, IMO, allow a much easier transition for many users, but I wonder if it propagates bad habits.
Thoughts?